Mp3.vue 4.11 KB
<template>
    <div class="p-1 flex flex-col mp3">
        <div v-if="file.annexFileName" class="text-12 mb-1 text-ellipsis">{{ file.annexFileName }}</div>
        <div class="flex items-center justify-between gap-x-2.5">
            <div class="shrink-0 play-bt" @click="start(file)">
                <doc-icon type="doc-play" v-if="!player.playing"/>
                <doc-icon type="doc-pause" v-else/>
            </div>
            <span class="shrink-0 time">{{timeFormat(player.duration)}}</span>
            <div class="grow progress">
                <van-slider v-model="player.currentTime" :max="sliderMax" :bar-height="6" :button-size="0"
                    @change="onProgress" />
                <!-- <div :style="`width: ${progress}%`"></div> -->
            </div>
            <span class="shrink-0 time" :style="`opacity: ${player.currentTime ? 1 : 0}`">
                {{ timeFormat(player.currentTime) }}</span>
        </div>
        <audio ref="audio" type="audio/mpeg" crossOrigin="anonymous" style="display: none"></audio>
    </div>
</template>

<script>
import { musicPlayer } from './mp3.js'
import { showToast } from 'vant'

export default {
    props: {
        file: { default: () => ({}) },
        activeMediaUrl: { default: '' }
    },
    data() {
        return {
            player: {},
            // 正在播放的items
            activeAudio: {},
        }
    },
    computed: {
        sliderMax() {
            return this.player.duration ? Math.floor(this.player.duration) : 100
        },
        progress() {
            if (!this.player.currentTime) return 0
            const temp = this.player.currentTime / this.player.duration
            return Math.round(temp * 1000) / 10
        }
    },
    mounted() {
        this.init()
    },
    methods: {
        init() {
            this.player = new musicPlayer(this.$refs.audio)
            this.player.init()
            this.player.setSrc(this.file.annexUrl)
            this.player.audioEl.onended = () => {
                console.log('播放结束')
                this.stop()
            }
        },
        start(item) {
            if (!item || !item.annexUrl) {
                showToast('文件获取失败')
                return
            }
            if (!this.player.audioCtx) {
                this.player.init()
                this.player.setSrc(item.annexUrl)
            }
            if (this.player.playing) {
                this.stop()
            } else {
                this.player.audioEl.play()
                this.activeAudio = item
                this.player.playing = true
                this.$emit('play', item)
            }
            console.log('this.player', this.player)
        },
        stop() {
            this.player.audioEl.pause()
            this.player.playing = false
        },
        timeFormat(value) {
            if (!value) {
                return '00:00'
            }
            let date = Math.ceil(value)
            let minutes = Math.floor(date / 60)
            let seconds = date % 60
            let format = '' + (minutes >= 10 ? minutes : '0' + minutes) + ':' + (seconds >= 10 ? seconds : '0' + seconds)
            return format
        },
        onProgress(value) {
            this.player.progressChange(value)
            this.player.playing = true
        }
    },
    watch: {
        activeMediaUrl(val) {
            console.log('activeMediaUrl', val)
            if (val !== this.file.annexUrl) {
                this.stop()
            }
        }
    }
}
</script>

<style lang="less" scoped>
.mp3 {
    background-color: #fff;
    .play-bt {
        display: inline-flex;
        width: 24px;
        height: 24px;
        align-items: center;
        justify-content: center;
        border-radius: 50%;
        background-color: #E4F2F0;
        font-size: 10px;
        padding-left: 2px;
        color: var(--van-primary-color);
    }
    .progress {
        // height: 6px;
        // border-radius: 4px;
        // background: #EFF2F7;
        // overflow: hidden;
        // text-align: left;
        // >div {
        //     height: 100%;
        //     background: #54CCBD;
        // }
    }
}
</style>