基于vue3音乐播放器进度条的实现
一、简介
一些零基础小白学习vue3
的开发记录,目标实现web端音乐播放器。github开发代码,欢迎一起交流学习。
二、相关准备
需求分析:
- 歌曲播放时,显示进度条,随着时间一起前进
- 拖动进度条,能够定位到歌曲对位位置播放
<video>
标签中可以通过监听H5
触发的媒体相关事件,精准控制音频内容- 说到进度条,在
html
里面首先想到的是input
组件,其中的range类型,通过vue的props传递属性可以很方便的实现想要的功能。 - 拖动进度条首先想到的vue的双向绑定,但这里有个问题就是:双向绑定数据后拖动改变时间,但是歌曲还在播放,穿过来的数据导致进度条向前。两者有明显冲突。
三、实现过程
滚动条的显示
获取相关数据
需要用到的<video>
中属性currentTime
、duration
及监听方法timeupdate
、durationchange
,将数据发送给对应需要用到的组件。
相关代码如下:
<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实例方法
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!