audio-tool.vue 2.18 KB
<script lang="ts" setup>
import {computed, onBeforeUnmount, shallowRef} from "vue";
import {useMediaControls} from "@vueuse/core";
import {IconPauseCircleFill, IconPlayCircleFill} from "@arco-design/web-vue/es/icon";

const props = defineProps<{ name?: string; url: string }>()

const audioRef = shallowRef<HTMLMediaElement>(new Audio(props.url))

const {playing, currentTime, duration} = useMediaControls(audioRef)

const formatDuration = (seconds: number) => new Date(1000 * seconds).toISOString().slice(14, 19)

const formatTooltip = (value: number) => formatDuration(value)

const startDuration = computed(() => formatDuration(currentTime.value))
const endDuration = computed(() => formatDuration(duration.value))

onBeforeUnmount(() => audioRef.value.pause())
</script>

<template>
    <a-card :bordered="false" @click.stop>
        <div class="play-name">{{ name }}</div>
        <div class="play-tool">
            <icon-pause-circle-fill class="btn" v-if="playing" @click="playing = !playing"/>
            <icon-play-circle-fill v-else class="btn" @click="playing = !playing"/>
            <div class="time">{{ startDuration }} / {{ endDuration }}</div>
            <a-slider v-model="currentTime" :max="Number(duration)" :format-tooltip="formatTooltip"
                      @mousedown="playing=false" @mouseup="playing = true"/>
        </div>
    </a-card>
</template>

<style scoped>
.play-name {
    font-size: 16px;
    font-weight: bold;
}

.play-tool {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: center;
    justify-content: flex-start;
    margin-top: 1em;

    .btn {
        color: #D62926;
        font-size: 25px;
    }

    .time {
        white-space: nowrap;
        font-size: 12px;
        color: #999999;
        padding: 0 15px 0 10px;
    }
}

::v-deep(div.arco-slider-track) {
    height: 10px;
}

::v-deep(div.arco-slider-track::before) {
    height: 4px;
}

::v-deep(div.arco-slider-bar) {
    height: 4px;
    background-color: #D62926;
}

::v-deep(div.arco-slider-btn) {
    width: 10px;
    height: 10px;
}

::v-deep(div.arco-slider-btn:after) {
    width: 10px;
    height: 10px;
    background-color: #D62926;
    border: 2px solid #D62926;
}
</style>