音频
function updateTime(e) {
if (!progressChanging.value) {
currentTime.value = e.target.currentTime
}
}
进度条:
function onProgressChanging(progress) {
progressChanging.value = true
isPlay.value = false
currentTime.value = duration.value * progress
}
function onProgressChanged(progress) {
progressChanging.value = false
isPlay.value = true
audioRef.value.currentTime = currentTime.value = duration.value * progress
}
<template>
<div class="progress-bar" ref="progressBarRef" @click="onClick">
<div class="bar-inner">
<div class="progress" ref="progressRef" :style="progressStyle"></div>
<!-- 移动端 -->
<div v-if="isMobile == true" class="progress-btn-wrapper" :style="btnStyle"
@touchstart.prevent="onTouchStart($event)" @touchmove.prevent="onTouchMove($event)"
@touchend.prevent="onTouchEnd">
<div class="progress-btn"></div>
</div>
<!-- PC端 -->
<div v-if="isMobile == false" ref="btnWrapperRef" class="progress-btn-wrapper" :style="btnStyle"
@mousedown.prevent="onMouseDown($event)" @mousemove.prevent @mouseup.prevent="onMouseUp">
<div class="progress-btn"></div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, defineProps, watch, computed, onMounted } from 'vue'
const offset = ref(0)
const progressRef = ref()
const progressBarRef = ref()
const progressBtnWidth = 16
const btnWrapperRef = ref()
const touch: any = {}
const mouse: any = {}
const isMobile = ref(false)
const mouseup_click_debug = ref(false)
const props = defineProps({
progress: {
type: Number,
default: 0
}
})
const emits = defineEmits(['progress-changing', 'progress-changed'])
onMounted(() => {
if (window.innerWidth <= 768) {
isMobile.value = true
} else {
isMobile.value = false
}
})
watch(() => props.progress, (newVal, oldVal) => {
//计算总进度条,除去按钮宽度
const barWidth = progressBarRef.value.clientWidth - progressBtnWidth
//计算出当前音频进度
offset.value = barWidth * newVal
})
const progressStyle = computed(() => {
//将当前音频进度style更换
return `width:${offset.value}px`
})
const btnStyle = computed(() => {
//按钮偏移量
return `transform:translate3d(${offset.value}px,0,0)`
})
//移动端进度条拖拽第一步点击
function onTouchStart(e) {
touch.x1 = e.touches[0].pageX
touch.beginWidth = progressRef.value.clientWidth
}
//移动端拖拽移动
function onTouchMove(e) {
const delta = e.touches[0].pageX - touch.x1
const tempWidth = touch.beginWidth + delta
const barWidth = progressBarRef.value.clientWidth - progressBtnWidth
const progress = Math.min(1, Math.max(tempWidth / barWidth, 0))
offset.value = barWidth * progress
//传递给父组件的进度
emits('progress-changing', progress)
}
//移动端拖拽移动结束
function onTouchEnd() {
const barWidth = progressBarRef.value.clientWidth - progressBtnWidth
const progress = progressRef.value.clientWidth / barWidth
emits('progress-changed', progress)
}
//PC端鼠标点击
function onMouseDown(e) {
mouse.x1 = e.pageX
mouse.beginWidth = progressRef.value.clientWidth
document.onmousemove = function (e) {
const delta = e.pageX - mouse.x1
const tempWidth = mouse.beginWidth + delta
const barWidth = progressBarRef.value.clientWidth - progressBtnWidth
const progress = Math.min(1, Math.max(tempWidth / barWidth, 0))
offset.value = barWidth * progress
emits('progress-changing', progress)
}
}
//PC端鼠标抬起
function onMouseUp() {
//mouseup与click的冲突,冲突在200ms以内
mouseup_click_debug.value = true
setTimeout(function () {
mouseup_click_debug.value = false;
}, 200);
const barWidth = progressBarRef.value.clientWidth - progressBtnWidth
const progress = progressRef.value.clientWidth / barWidth
document.onmousemove = null
emits('progress-changed', progress)
}
//点击定位到哪个进度
function onClick(e) {
if(mouseup_click_debug.value = true){
return
}else{
const rect = progressBarRef.value.getBoundingClientRect()
const offsetWidth = e.pageX - rect.left
const barWidth = progressBarRef.value.clientWidth - progressBtnWidth
const progress = offsetWidth / barWidth
emits('progress-changed', progress)
}
}
</script>
<style scoped>
.progress-bar {
height: 30px;
width: 100%;
}
.bar-inner {
position: relative;
top: 13px;
height: 4px;
background: rgba(0, 0, 0, 0.3);
}
.progress {
position: absolute;
height: 100%;
background: #0FA2FF;
}
.progress-btn-wrapper {
position: absolute;
left: -8px;
top: -13px;
width: 30px;
height: 30px;
}
.progress-btn {
position: relative;
top: 7px;
left: 7px;
box-sizing: border-box;
width: 16px;
height: 16px;
border: 3px solid #fff;
border-radius: 50%;
background: #0FA2FF;
}
</style>