vue中如何实现音频轮流播放的功能?

DongHY1
  • 3
新手上路,请多包涵

小弟刚学前端,在写自己的demo时有一个需求。
点击START按钮,播放音频A,等待1秒,再播放音频B。如此循环
点击STOP按钮,停止播放

请问如何实现呢?谢谢🙏
这是我的代码

<template>
  <div id="Metronome">
    <div class="container">
      <div class="metronome">
        <div class="bpm-display">
          <span class="tempo">{{ tempo }}</span>
          <span class="bpm">BPM</span>
        </div>
        <div class="tempo-text">
          <div v-if="this.tempo <= 40">Super Slow</div>
          <div v-if="this.tempo > 40 && this.tempo <= 80">Slow</div>
          <div v-if="this.tempo > 80 && this.tempo <= 120">Getting there</div>
          <div v-if="this.tempo > 120 && this.tempo <= 180">
            Nice and Steady
          </div>
          <div v-if="this.tempo > 180 && this.tempo <= 220">Rock n' Roll</div>
          <div v-if="this.tempo > 220 && this.tempo <= 240">Funky Stuff</div>
          <div v-if="this.tempo > 240 && this.tempo <= 260">Relax Dude</div>
          <div v-if="this.tempo > 260 && this.tempo <= 280">
            Eddie Van Halen
          </div>
        </div>
        <div class="tempo-settings">
          <div class="adjust-tempo-btn decrease-tempo" @click="decreaseTempo">
            -
          </div>
          <input
            type="range"
            min="20"
            max="280"
            step="1"
            class="slider"
            v-model.number="tempo"
          />
          <div class="adjust-tempo-btn increase-tempo" @click="increaseTempo">
            +
          </div>
        </div>
        <button class="start-stop" @click="changeStart()">
          {{ !isStart ? "START" : "STOP" }}
        </button>
        <audio ref="click1" src="../sound/click1.mp3"></audio>
        <audio ref="click2" src="../sound/click2.mp3"></audio>
        <audio></audio>
        <div class="measures">
          <div class="subtract-beats stepper" @click="decreaseBeat">-</div>
          <div class="measure-count">{{ beat }}</div>
          <div class="add-beats stepper" @click="increaseBeat">+</div>
        </div>
        <span class="beats-per-measure-text">Beats per measure</span>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "Metronome",
  data() {
    return {
      tempo: 140,
      beat: 4,
      isStart: false,
    };
  },
  methods: {
    increaseTempo() {
      if (this.tempo >= 280) return;
      this.tempo++;
    },
    decreaseTempo() {
      if (this.tempo <= 20) return;
      this.tempo--;
    },
    increaseBeat() {
      if (this.beat < 12) {
        this.beat++;
      }
    },
    decreaseBeat() {
      if (this.beat > 2) {
        this.beat--;
      }
    },
    startPlay() {
      //play A
      this.$refs.click1.play();
      console.log("click1 is playing!")
      //play B after 1000ms
      setInterval(this.playClick2,1000);
      },
    playClick2(){
      this.$refs.click2.play();
      console.log("click2 is playing!")
    },
    stopPlay() {
      clearInterval(this.playClick2);
    },
    changeStart() {
      this.isStart = !this.isStart;
      if (this.isStart) {
        this.startPlay();
      } else {
        this.stopPlay();
      }
    },
  },
};
</script>
回复
阅读 280
1 个回答

大概这样吧,代码直接写的,没跑过不知道会不会有问题,只提供个大概思路

创建一个LoopAudio类的对象,来控制开始结束,这样比较清晰

interface LoopListItem {
    audio: HTMLAudioElement,
    loopTime: number
}

class LoopAudio {

    private start = false;

    private activeIndex = 0;

    private loopID = 0;

    private loopList: LoopListItem[];

    constructor (loopList: LoopListItem[]) {
        this.loopList = loopList || [];
  }

  private loop() {
    this.playAudio(this.activeIndex, () => {
      let audioOption = this.loopList[this.activeIndex];

      if (audioOption) {
        audioOption.audio.pause();
      }

      this.activeIndex = (this.activeIndex + 1) % this.loopList.length;
      this.loop();
    });
    }

    startLoop () {
        if (!this.loopList.length || this.start) {
            return;
      }
      this.start = true;
      this.loop();
  }

  stopLoop() {
    if (!this.start) {
      return;
    }
    clearTimeout(this.loopID);
    this.loopID = 0;
    this.activeIndex = 0;
    this.start = false;
    this.loopList.forEach(audioOption => {
      audioOption.audio.pause();
    });
  }

  playAudio(index: number, nextFn?: Function) {
    let audioOption = this.loopList[index];
    if (!audioOption) {
      return;
    }
    let { audio, loopTime } = audioOption;
    if (!audio.duration) {
      return;
    }
    if (audio.currentTime >= audio.duration) {
      audio.currentTime = 0;
    }
    
    audio.play();

    if (nextFn) {
      this.loopID = setTimeout(nextFn, loopTime);
    }
  }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
你知道吗?

宣传栏