You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
3.6 KiB
158 lines
3.6 KiB
<template> |
|
<!-- 音频播放器组件 --> |
|
<view v-if="url" class="flex justify-between align-center audio"> |
|
<view class="mr-3" @click="start(audioId)"> |
|
<image :src="startPic" class="icon" v-show="!status"></image> |
|
<image :src="endPic" class="icon" v-show="status"></image> |
|
</view> |
|
<view class="flex-1"> |
|
<slider |
|
@change="changeAudio" |
|
:activeColor="activeColor" |
|
:min="0" |
|
:max="duration.toFixed(0)" |
|
:value="currentTime.toFixed(0)" |
|
:step="0.1" |
|
></slider> |
|
</view> |
|
<view class="ml-3">{{ getTime(Math.round(currentTime)) }}</view> |
|
</view> |
|
</template> |
|
|
|
<script> |
|
export default { |
|
data() { |
|
return { |
|
context: null, |
|
currentTime: 0, |
|
duration: 100, |
|
status: false, |
|
}; |
|
}, |
|
props: { |
|
url: String, |
|
activeColor: { |
|
type: String, |
|
default: "#0E7EFC", |
|
}, |
|
startPic: String, |
|
endPic: String, |
|
audioId: [String, Number], |
|
}, |
|
created() { |
|
this.context = uni.createInnerAudioContext(); |
|
this.context.src = this.url; |
|
this.onTimeUpdate(); |
|
this.onCanplay(); |
|
this.onEnded(); |
|
uni.$on("stop", (id) => { |
|
if (id && id != this.audioId) { |
|
this.context.stop(); |
|
this.status = false; |
|
} else if (!id) { |
|
this.context.stop(); |
|
this.status = false; |
|
} |
|
}); |
|
}, |
|
methods: { |
|
start(id) { |
|
//点击播放 |
|
let audioId = id; |
|
if (this.status) { |
|
this.context.pause(); |
|
this.status = !this.status; |
|
} else { |
|
uni.$emit("stop", id); |
|
this.context.play(); |
|
this.status = !this.status; |
|
} |
|
}, |
|
onCanplay() { |
|
//进入可播放状态 |
|
this.context.onCanplay(() => { |
|
this.context.duration; |
|
setTimeout(() => { |
|
this.duration = this.context.duration; |
|
}, 1000); |
|
}); |
|
}, |
|
onTimeUpdate() { |
|
//音频播放进度 |
|
this.context.onTimeUpdate(() => { |
|
if (!Number.isFinite(this.context.duration)) { |
|
this.duration = this.context.currentTime + 10; |
|
this.currentTime = this.context.currentTime; |
|
} else { |
|
this.duration = this.context.duration; |
|
this.currentTime = this.context.currentTime; |
|
} |
|
}); |
|
}, |
|
onEnded() { |
|
//播放结束 |
|
this.context.onEnded(() => { |
|
this.status = false; |
|
this.currentTime = 0; |
|
}); |
|
}, |
|
changeAudio(e) { |
|
let paused = this.context.paused; |
|
this.context.pause(); |
|
this.context.seek(e.detail.value); |
|
if (!paused) { |
|
this.context.play(); |
|
} |
|
}, |
|
getTime(time) { |
|
let m = parseInt(time / 60); |
|
let s = time % 60; |
|
return this.towNum(m) + ":" + this.towNum(s); |
|
}, |
|
towNum(num) { |
|
if (num >= 10) { |
|
return num; |
|
} else { |
|
return "0" + num; |
|
} |
|
}, |
|
}, |
|
}; |
|
</script> |
|
|
|
<style> |
|
.audio { |
|
background: #f4f4f4; |
|
padding: 20rpx; |
|
} |
|
|
|
.icon { |
|
width: 80rpx; |
|
height: 80rpx; |
|
} |
|
|
|
.flex { |
|
display: flex; |
|
flex-direction: row; |
|
} |
|
|
|
.justify-between { |
|
justify-content: between; |
|
} |
|
|
|
.align-center { |
|
align-items: center; |
|
} |
|
|
|
.flex-1 { |
|
flex: 1; |
|
} |
|
|
|
.ml-3 { |
|
margin-left: 30rpx; |
|
} |
|
|
|
.mr-3 { |
|
margin-right: 30rpx; |
|
} |
|
</style>
|
|
|