最新公告
  • 欢迎您光临网站无忧模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 基于vue3音乐播放器进度条的实现

    正文概述 掘金(用户1168630712647)   2021-01-19   854

    基于vue3音乐播放器进度条的实现

    一、简介

    一些零基础小白学习vue3的开发记录,目标实现web端音乐播放器。github开发代码,欢迎一起交流学习。

    二、相关准备

    需求分析:

    1. 歌曲播放时,显示进度条,随着时间一起前进
    2. 拖动进度条,能够定位到歌曲对位位置播放
    • <video>标签中可以通过监听H5触发的媒体相关事件,精准控制音频内容
    • 说到进度条,在html里面首先想到的是input组件,其中的range类型,通过vue的props传递属性可以很方便的实现想要的功能。
    • 拖动进度条首先想到的vue的双向绑定,但这里有个问题就是:双向绑定数据后拖动改变时间,但是歌曲还在播放,穿过来的数据导致进度条向前。两者有明显冲突。

    三、实现过程

    滚动条的显示

    获取相关数据

    需要用到的<video>中属性currentTimeduration及监听方法timeupdatedurationchange,将数据发送给对应需要用到的组件。

    相关代码如下:

    <template>
      <audio
        ref="audio"
        class="audio-player"
        :src="src"
        ···
        @timeupdate="timeupdateListener"
        @durationchange="durationchangeListener"
        ···
      / >
    </ template>
    export default {
      name: "Audio",
      emits: {
        "update-currentTime": null,
        "update:duration": payload => {
          if (payload !== 0) {
            return true;
          }
          console.warn("获取歌曲长度失败,值为", payload);
          return false;
        }
      },
      ···
      methods: {
        timeupdateListener(e) {
          //元素的currentTime属性表示的时间已经改变。
          this.$emit("update-currentTime", this.$refs.audio.currentTime);
        },
        durationchangeListener() {
          //元信息已载入或已改变,表明媒体的长度发生了改变
          this.$emit("update:duration", this.$refs.audio.duration);
        },
        ···
      }
    };
    

    利用数据显示进度条

    这里查阅相关文档修改进度条样式,相关style这里不显示了。然后对通过props接收到的值进行显示也没有问题。

    相关代码如下:

    <template>
      <div class="player-content">
        <div class="progress-bar">
          <input
            type="range"
            ref="progress"
            :class="{ active: isTouch }"
            min="0"
            v-model="currentTime"   //待会将去除
            :max="duration"
            step="0.05"
            ···
          />
          <div class="progerss-time">
            <span class="left">{{ parseTimeString(currentTime) }}</span>
            <span class="right">{{ parseTimeString(duration) }}</span>
          </div>
        </div>
      </div>
    </template>
    <script>
    export default {
      name: "PlayerContent",
      props: {
        currentTime: {
          type: Number,
          default: 0
        },
        duration: {
          type: Number,
          default: 1
        }
      },
      data() {
        return {
          isTouch: false
        };
      },
      methods: {
        parseTimeString(num) {
          let min = Math.floor(num / 60);
          let sec = Math.floor(num - min * 60);
          return `${min}:${sec}`;
        },
        ···
      }
    };
    </script>
    

    拖动进度条定位功能的实现

    这里首先考虑到分析过的问题2,决定再显示一个一样的input标签,绑定临时定义的变量进行单向控制。也就是从video传过来的值显示一个进度条,临时进度条拖动后双向绑定的值传回给video设置currentTime

    然后测试了之后经过分析还是发现不能通过双向绑定实现,这样数据流形成了闭环,拖动产生的Time和传过来currentTime会相互干扰

    分析过后,觉得只要没有控制的时候接收传过来的currentTime,但是控制的时候取消接收,这时候将拖动产生的Time传给video进行设置就行了。

    在vue文档中查了一下,$watch这个实例方法监听的时候会返回一个unwatch取消监听函数,那么就很容易实现想要的功能了。

    相关代码如下,其中上面绑定的v-model="currentTime"需要去掉:

    export default {
      name: "PlayerContent",
      emits: {
        "set-currentTime": null
      },
      ···
      data() {
        return {
          isTouch: false
        };
      },
      created() {
        this.unwatch = this.progressWatcher();
      },
      methods: {
          ···
        progressWatcher() {
          return this.$watch("currentTime", (newVal, oldVal) => {
            this.$refs.progress.value = newVal;
          });
        },
        touchStart(e) {
          // 暂停监听value
          this.unwatch();
          this.isTouch = true;
        },
        touchEnd(e) {
          // 跳转至对应时间
          this.$emit("set-currentTime", Number.parseFloat(e.target.value));
          // 开始监听
          this.unwatch = this.progressWatcher();
          // 改变样式
          this.isTouch = false;
        }
      }
    };
    

    四、实现效果

    这里不贴图了,完整的详细代码放在github代码,可以拉下来,测试一下效果

    五、参考资料整理

    • video标签对应的媒体相关事件
    • range类型的input标签
    • vue文档watch实例方法

    下载网 » 基于vue3音乐播放器进度条的实现

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元