123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- <template>
- <view v-if='url' class='xpj-audio-box'>
- <view @click='startPlay' v-if="showImg">
- <image :src="startImg" v-show='!status' class="voice_icon"></image>
- <image :src="pauseImg" v-show='status' class="voice_icon"></image>
- </view>
- <view class="flexB voice">
- <view class='current-time time-text' :style="{color:textColor}">{{format(currentTime)}}</view>
- <view class='audio-action'>
- <slider @change='changeAudio' :activeColor="activeColor" :block-color="blockColor"
- :backgroundColor="backgroundColor" block-size="12" :disabled="currentTime==0" :min='0'
- :max='duration.toFixed(0)' :value='currentTime.toFixed(0)' :step='0.1'>
- </slider>
- </view>
- <view class='duration-time time-text' :style="{color:textColor}">{{format(duration)}}</view>
- </view>
- </view>
- </template>
- <script>
- export default {
- data() {
- return {
- xpjAudio: null,
- currentTime: 0,
- duration: 100,
- status: false
- }
- },
- props: {
- showImg: {
- type: Boolean,
- default: true
- },
- url: String,
- activeColor: {
- type: String,
- default: '#f00'
- },
- startImg: {
- type: String,
- default: '/static/imgs/voice/start.png'
- },
- pauseImg: {
- type: String,
- default: '/static/imgs/voice/pause.png'
- },
- blockColor: {
- type: String,
- default: '#FF0000'
- },
- backgroundColor: {
- type: String,
- default: '#eee'
- },
- blockSize: {
- type: Number,
- default: 14,
- },
- textColor: {
- type: String,
- default: '#f00'
- }
- },
- created() {
- this.xpjAudio = uni.createInnerAudioContext();
- this.xpjAudio.src = this.url;
- // uni.setInnerAudioOption({
- // obeyMuteSwitch: false
- // })
- this.onTimeUpdate();
- this.onCanplay();
- this.onEnded();
- uni.$on('stop', () => {
- this.xpjAudio.stop()
- this.status = false
- })
- },
- methods: {
- //开始播放事件
- startPlay() {
- if (this.status) {
- this.xpjAudio.pause();
- this.status = !this.status;
- } else {
- uni.$emit('stop')
- this.xpjAudio.seek(this.currentTime)
- this.xpjAudio.play()
- this.status = !this.status;
- }
- },
- //进入可播放状态
- onCanplay() {
- this.xpjAudio.onCanplay(() => {
- this.xpjAudio.duration;
- setTimeout(() => {
- this.duration = this.xpjAudio.duration;
- })
- })
- },
- //音频播放进度更新
- onTimeUpdate() {
- this.xpjAudio.onTimeUpdate(() => {
- this.currentTime = this.xpjAudio.currentTime;
- })
- },
- //播放结束事件
- onEnded() {
- this.xpjAudio.onEnded(() => {
- this.status = false;
- this.currentTime = 0;
- })
- },
- // 拖拽播放事件
- changeAudio(e) {
- let paused = this.xpjAudio.paused;
- this.xpjAudio.pause();
- this.xpjAudio.seek(e.detail.value)
- if (!paused) {
- this.xpjAudio.play();
- }
- },
- format(num) {
- return '0'.repeat(2 - String(Math.floor(num / 60)).length) + Math.floor(num / 60) + ':' + '0'.repeat(2 -
- String(Math.floor(num % 60)).length) + Math.floor(num % 60)
- },
- },
- destroyed() {
- this.xpjAudio.stop();
- },
- watch: {
- url(newVal) {
- if (newVal) {
- this.xpjAudio.stop();
- this.xpjAudio.src = newVal;
- this.currentTime = 0;
- this.onTimeUpdate();
- this.onCanplay();
- this.onEnded();
- this.status = false
- }
- }
- }
- }
- </script>
- <style lang="scss">
- .xpj-audio-box {
- width: 100%;
- text-align: center;
- padding: 30rpx;
- box-sizing: border-box;
- .title {
- font-size: 32rpx;
- font-weight: bold;
- padding: 40rpx 0 60rpx;
- }
- .voice {
- height: 100%;
- }
- .voice_icon {
- width: 100rpx;
- height: 100rpx;
- margin-bottom: 78rpx;
- }
- .play-btn {
- font-size: 0;
- margin-right: 10rpx;
- .play-icon {
- width: 40rpx;
- height: 40rpx;
- }
- }
- .time-text {
- font-size: 28rpx;
- }
- .audio-action {
- flex: 1;
- }
- }
- </style>
|