关于“vue2.0实现音乐/视频播放进度条组件”的攻略,我们需要考虑到以下几个方面:
- 组件设计
- 组件实现
- 组件使用
组件设计
在设计组件时,我们需要考虑以下几个方面:
- 组件的功能需求:播放进度条组件需要提供能够显示当前播放进度和总时长的功能,以及能够拖动改变播放进度的功能。
- 状态管理:我们需要维护当前播放时间、总时长和拖动状态的状态。
- 组件结构:播放进度条组件可以横向或竖向显示,我们可以考虑使用flex布局或absolute定位实现。
组件实现
在组件实现时,我们需要完成以下几个步骤:
- 组件结构设计:在template模板中使用 div、span、input等基本html元素构建组件结构。
- 数据管理:使用 props将播放的总时长和当前播放时间传入组件,通过data来定义组件需要维护的内部状态,包括播放开始时间、拖动状态和当前进度等值。
- 事件处理:使用 @mousedown、@mousemove、@mouseup和 @click 等事件处理函数,完成播放进度条拖动、重新开始播放等功能。
- 时长转换:处理组件接收到的时间单位,可以通过 Math.floor、PadStart 等API处理显示效果。
下面是一个基础示例:
<template>
<div class="play-progress-bar">
<span class="current-time">{{ currentTime }}</span>
<input
class="progress-bar"
type="range"
min="0"
max="100"
@mousedown="startDrag"
@mousemove="dragging"
@mouseup="stopDrag"
@click="seekTo"
:value="progress"
/>
<span class="total-time">{{ totalTime }}</span>
</div>
</template>
<script>
export default {
name: "play-progress",
props: {
currentTime: Number, //当前播放时间
totalTime: Number //总时长
},
data() {
return {
duration: 0, //播放开始时间
dragging: false, //是否正在拖动
progress: null //当前进度
};
},
methods: {
startDrag() {
this.dragging = true;
this.duration = this.currentTime;
},
dragging(evt) {
if (!this.dragging) return;
const target = evt.target;
const rect = target.getBoundingClientRect();
const offsetX = evt.clientX - rect.left;
const progress = offsetX / target.offsetWidth;
this.progress = progress;
},
stopDrag(evt) {
if (!this.dragging) return;
this.dragging = false;
const target = evt.target;
const rect = target.getBoundingClientRect();
const offsetX = evt.clientX - rect.left;
const progress = offsetX / target.offsetWidth;
this.progress = progress;
this.seekTo();
},
seekTo() {
const time = this.progress * this.totalTime;
this.$emit("change", time);
this.duration = time;
}
},
computed: {
progress: {
set(val) {
if (!this.dragging) return;
this.$emit("change", val * this.totalTime);
this.duration = val * this.totalTime;
},
get() {
return this.totalTime && this.currentTime
? (this.currentTime / this.totalTime) * 100
: 0;
}
}
}
};
</script>
<style scoped>
.play-progress-bar {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 30px;
background-color: #aaa;
position: relative;
}
.progress-bar {
width: 100%;
height: 4px;
-webkit-appearance: none;
background-color: #333;
outline: none;
cursor: pointer;
position: relative;
z-index: 1;
}
.progress-bar::-webkit-slider-thumb {
-webkit-appearance: none;
width: 8px;
height: 8px;
border-radius: 50%;
background-color: #333;
position: relative;
z-index: 2;
}
.current-time,
.total-time {
margin-left: 10px;
margin-right: 10px;
font-size: 12px;
color: #333;
}
</style>
除此之外,我们还可以根据具体需求进行进一步的组件优化和功能拓展,例如对进度条进行美化、添加缓存等功能。
下面是一个进阶示例:
<template>
<div class="play-progress-bar">
<div class="progress-bar-wrap">
<div class="progress-buffer-bar" :style="{ width: bufferedProgress + '%' }"></div>
<div class="progress-point" :style="{ left: progress + '%' }">
<span class="current-time">{{ currentTime | formatTime }}</span>
<span class="point" @click="seekTo"></span>
</div>
<div class="progress-play-bar" :style="{ width: progress + '%' }"></div>
</div>
<span class="total-time">{{ totalTime | formatTime }}</span>
</div>
</template>
<script>
export default {
name: "play-progress",
props: {
currentTime: Number,
totalTime: Number,
bufferProgress: Number
},
filters: {
formatTime(value) {
if (!value) return "00:00";
let minute = Math.floor(value / 60);
let second = Math.floor(value % 60);
minute = minute < 10 ? "0" + minute : minute;
second = second < 10 ? "0" + second : second;
return `${minute}:${second}`;
}
},
computed: {
progress() {
if (this.totalTime === 0) {
return 0;
} else {
return (this.currentTime / this.totalTime) * 100;
}
},
bufferedProgress() {
if (this.totalTime === 0) {
return 0;
} else {
return (this.bufferProgress / this.totalTime) * 100;
}
}
},
methods: {
seekTo(evt) {
evt.stopPropagation();
const target = evt.target;
const rect = target.getBoundingClientRect();
const offsetX = evt.clientX - rect.left;
const progress = offsetX / target.offsetWidth;
this.$emit("seekto", progress);
}
}
};
</script>
<style scoped>
.play-progress-bar {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 30px;
background-color: #aaa;
padding: 0 10px;
position: relative;
}
.progress-bar-wrap {
width: 100%;
height: 4px;
background-color: #ddd;
cursor: pointer;
position: relative;
}
.progress-buffer-bar {
background-color: #666;
height: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 0;
}
.progress-play-bar {
background-color: #333;
height: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 1;
}
.progress-point {
position: absolute;
top: -14px;
left: 0;
z-index: 2;
display: flex;
align-items: center;
justify-content: center;
}
.progress-point .current-time {
display: inline-block;
height: 16px;
line-height: 16px;
font-size: 12px;
padding: 0 6px;
margin-right: 8px;
border-radius: 2px;
background-color: #666;
color: #fff;
}
.progress-point .point {
width: 8px;
height: 8px;
border-radius: 50%;
background-color: #333;
cursor: pointer;
}
.total-time {
font-size: 12px;
color: #333;
}
</style>
在这个示例中,我们添加了缓冲进度条,支持点击缓冲区间快速跳转到指定播放位置,并添加了时间格式化Filter等功能。
组件使用
在实际使用我们的播放进度条组件时,我们只需要将组件引用在需要播放的组件中,并传递相应的参数即可。例如:
<template>
<section>
<h2>MUSIC</h2>
<audio src="./music.mp3" ref="audio" @timeupdate="updateTime" @progress="updateBuffer"></audio>
<play-progress
:current-time="currentTime"
:total-time="totalTime"
:buffer-progress="bufferProgress"
@seekto="handleSeekTo"
/>
</section>
</template>
<script>
import PlayProgress from "./PlayProgress";
export default {
name: "Music",
components: {
PlayProgress
},
data() {
return {
currentTime: 0,
totalTime: 0,
bufferProgress: 0
};
},
methods: {
updateTime(evt) {
this.currentTime = evt.target.currentTime;
this.totalTime = evt.target.duration;
},
updateBuffer(evt) {
if (evt.target.buffered.length) {
this.bufferProgress = evt.target.buffered.end(0);
}
},
handleSeekTo(progress) {
const time = progress * this.totalTime;
this.$refs.audio.currentTime = time;
}
}
};
</script>
<style>
h2 {
font-size: 24px;
font-weight: bold;
margin-bottom: 10px;
}
</style>
在这个示例中,我们在一个Music组件中引用了播放进度条组件,使用Audio元素播放音频,并通过$refs获取Audio组件实例,获取当前播放进度和总时长、缓冲进度并传递给播放进度条组件。当播放进度条组件发生变化时,我们通过@seekto事件处理函数和$refs获取的Audio组件实例来更新播放进度和总时长。
以上便是solidot教程中“vue2.0实现音乐/视频播放进度条组件”的完整攻略。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vue2.0实现音乐/视频播放进度条组件 - Python技术站