HTML5-Audio实战总结

最近闲暇时在使用Electron做桌面端应用(仿网易云桌面客户端)于是有接触到audio。由于很久没有写过这标签了 特来此详细做个笔记,方便自己以后查阅。

先放一个auido标签 让他动起来

   <audio 
   		:src="https://music.163.com/song/media/outer/url?id=65847.mp3"
		controls
    ></audio>

一、Audio 对象

Audio 对象属性

属性 描述 博主提示
audioTracks 返回表示可用音频轨道的 AudioTrackList 对象。 任何主流浏览器都不支持 audioTracks 属性。
autoplay 设置或返回是否在就绪(加载完成)后随即播放音频。 如果设置了该属性,音频(加载完成)将自动播放。
buffered 返回表示音频已缓冲部分的 TimeRanges 对象。
controller 返回表示音频当前媒体控制器的 MediaController 对象。 目前没有主流浏览器支持 controller 属性。
controls 设置或返回音频是否应该显示控件(比如播放/暂停等)。 设置就可以显示控件,但是每个浏览器都有自己显示auido的样式
crossOrigin 设置或返回音频的 CORS 设置。 这个确实没太懂哈 按常理,跨域在头部设置或者config配置 或者后端配置
currentSrc 返回当前音频的 URL。 只读
currentTime 设置或返回音频中的当前播放位置(以秒计)。 可写可读
defaultMuted 设置或返回音频默认是否静音。 可写可读
defaultPlaybackRate 设置或返回音频的默认播放速度。 可写可读
duration 返回音频的长度(以秒计)。 只读
ended 返回音频的播放是否已结束。 只读
error 返回表示音频错误状态的 MediaError 对象。
loop 设置或返回音频是否应在结束时再次播放。 可写可读
mediaGroup 设置或返回音频所属媒介组合的名称。 可写可读
muted 设置或返回是否关闭声音。 可写可读
networkState 返回音频的当前网络状态。 0 - 音频尚未初始化;1 - 音频是活动的且已选取资源,但并未使用网络2 - 浏览器正在下载数据;3 - 未找到音频来源
paused 设置或返回音频是否暂停。 只读
playbackRate 设置或返回音频播放的速度。 可写可读,例值:1.0 正常速度;0.5 半速(更慢);2.0 倍速(更快);-1.0 向后;正常速度-0.5 向后半速 等
played 返回表示音频已播放部分的 TimeRanges 对象。
preload 设置或返回音频的 preload 属性的值。 可写可读,是否在页面加载后载入音频。
readyState 返回音频当前的就绪状态。 可写可读
seekable 返回表示音频可寻址部分的 TimeRanges 对象。
seeking 返回用户当前是否正在音频中进行查找。
src 设置或返回音频的 src 属性的值。 可写可读
textTracks 返回表示可用文本轨道的 TextTrackList 对象。
volume 设置或返回音频的音量。 规定音频/视频的当前音量。必须是介于 0.0 与 1.0 之间的数字。可写可读

Audio 对象方法

方法 描述
addTextTrack() 向音频添加新的文本轨道。
canPlayType() 检查浏览器是否能够播放指定的音频类型。
fastSeek() 在音频播放器中指定播放时间。
getStartDate() 返回新的 Date 对象,表示当前时间线偏移量。
load() 重新加载音频元素。
play() 开始播放音频。
pause() 暂停当前播放的音频。

二、播放器代码

template

    <div class="audio">
      <audio @ended="next(currentSongUnit.afterId)" ref="audio" @timeupdate="timeupdate"
             preload="auto" :src="audioSrc" />
      <div class="audio-btn fac">
      	<!-- 上一首 -->
        <i @click="next(currentSongUnit.beforeId)"class="iconfont icon-lastSong"/>
        <!-- 播放 -->
        <i @click="play()" v-show="isPause" class="iconfont icon-play" />
        <!-- 暂停 -->
        <i @click="stop()" v-show="!isPause" class="iconfont icon-paused" />
        <!-- 下一首 -->
        <i @click="next(currentSongUnit.afterId)" class="iconfont icon-nextSong"/>
      </div>
      <div class="audio-progressBar fbc">
      	<!-- 歌曲当前播放时间 -->
        <p class="start-tiem audio-tiem">{
    
    {
    
     staratTime }}</p>
        <!-- 进度条 -->
        <div>
          <el-slider v-model="progressBarValue" :show-tooltip="false" @change="sliderChange"/>
        </div>
        <!-- 歌曲总时长 -->
        <p class="end-tiem audio-tiem">{
    
    {
    
     allTime }}</p>
      </div>
    </div>

script

#部分代码涉及接口 接口我并没有写出来 不好意思
<script>
import {
    
     search, getSongDetail } from '@/api/find';
export default {
    
    
  name: 'myFooter',

  components: {
    
    },

  data() {
    
    
    return {
    
    
      audio: '',//audio的ref
      hotList: [],//歌曲完整列表
      staratTime: '00:00', //当前播放时间
      progressBarValue: 0,//进度条显示长度 默认为0 范围为0-100 使用前转换
      allTime: '00:00', //歌曲总时间
      isPause: true, //是否暂停 默认暂停
      songsIdList: [], //所有歌曲简化信息
      currentSongUnit: {
    
    }, //当前歌曲部分信息
    };
  },

  computed: {
    
    
    //歌曲的url
    audioSrc() {
    
    
      return `https://music.163.com/song/media/outer/url?id=${
      
      this.currentSongUnit.id}.mp3`;
    },
  },
  
  watch: {
    
    
  	//当歌曲audioSrc 发生变化时 重新执行load加载歌曲及 getSongDetail获取歌曲相信信息
    audioSrc() {
    
    
      this.audio.load();
      this.getSongDetail();
    },
  },

  mounted() {
    
    
    this.audio = this.$refs.audio; //获取audio的ref
    this.searchMusic();
  },

  methods: {
    
    
    //search接口获取陈奕迅的歌单数据 重写数组 只保留id 名字 上/下首歌曲id 
    async searchMusic() {
    
    
      const params = {
    
     keywords: '陈奕迅' };
      const {
    
     result } = await search(params);
      const hotList = result.songs;
      //获取上一曲下一曲id 当前歌曲id,name 重置id数组
      const songsIdList = hotList.map((item, index) => {
    
    
        const afterId = hotList[index + 1] ? hotList[index + 1].id : null;
        const beforeId = hotList[index - 1] ? hotList[index - 1].id : null;
        const arr = {
    
     id: item.id, name: item.name, afterId, beforeId };
        return arr;
      });
      this.hotList = hotList;//获取到的歌单信息
      this.songsIdList = songsIdList;//重写的数组
      this.currentSongUnit = songsIdList[0];//默认当前播放为第一条
      this.getSongDetail();//执行getSongDetail
    },
    //getSongDetail接口获取当前播放歌曲的详细信息 歌单信息内歌曲list信息不够完善
    async getSongDetail() {
    
    
      const {
    
     songs } = await getSongDetail(this.currentSongUnit.id);
      const song = songs[0];
      //处理song.ar对象内歌手大于一位时 拼接/ 例: 陈奕迅/薛之谦
      const singer =  song.ar.length > 1
          ? song.ar.map((it) => it.name).join(' / ')
          : song.ar[0].name;
      this.currentSongUnit = {
    
    
        ...this.currentSongUnit,
		songName: song.name,
		songAvatar: song.al.picUrl,
        singer,
      };
      this.play();//执行play方法 播放
    },
    //下一首 上一首  播放完毕也回执行该方法
    next(id) {
    
    
      if (!id) {
    
      return false; }
      const nextList = this.songsIdList.find((it) => it.id === id);
      this.currentSongUnit = nextList;
    },
    //暂停
    stop() {
    
    
      this.audio.pause();
      this.isPause = true;
    },
    //播放 获取完整时间
    play() {
    
    
      this.allTime = this.filterDuration(this.audio.duration);
      this.audio.play();
      this.isPause = false;
    },
    //当歌曲实时播放时 获取当前播放时间 设置滚动条位置
    timeupdate() {
    
    
      this.staratTime = this.filterDuration(this.audio.currentTime);
      this.progressBarValue =
        (this.audio.currentTime / this.audio.duration) * 100;
      // console.log(this.audio.currentTime / this.audio.duration);
    },
    //拉动滚动条时候出发 松手触发
    sliderChange(e) {
    
    
      this.audio.currentTime = (e / 100) * this.audio.duration;
    },
    // 静音/禁止静音
    muted() {
    
    
      this.audio.muted = !this.audio.muted;
    },
    //转化时长显示
    filterDuration(s) {
    
    
      if (typeof s !== 'number') {
    
    
        throw new Error('传入时长需为数字类型');
      }
      let hour = Math.floor(s / 3600);
      let min = Math.floor((s % 3600) / 60);
      let sec = Math.floor(s % 60);

      hour = hour < 10 ? `0${
      
      hour}` : hour;
      min = min < 10 ? `0${
      
      min}` : min;
      sec = sec < 10 ? `0${
      
      sec}` : sec;

      return `${
      
      min}:${
      
      sec}`;
    },
  },
};
</script>

Supongo que te gusta

Origin blog.csdn.net/weixin_45815859/article/details/115164426
Recomendado
Clasificación