对于音频标签无法自定义如何解决:
样式:
功能:
倍数播放,可拖拽进度条
引用方法:
import cnAudio from './cn-audio';
<cnAudio :audioUrl='音频文件'/>
组件内容:
[代码片段](https://code.juejin.cn/pen/7121921287358234654)<-- html -->
<template>
<div class="add-summary-audio-new" :class="{'audio-box' : audioPlay === '1'}">
<div class="audio-control">
<div class="audio-play-control" @click="changeAudioPlay">
<i class="iconfont" v-if="audioPlay === '1'"></i>
<i class="iconfont" v-else></i>
</div>
</div>
<div class="audio-download">
<i class="audio-download-i"> {{ audio.currentTimeText }} / </i>
<i class="audio-download-i">
{{ audio.totalTimeText }}
</i>
</div>
<div class="audio-progress">
<el-slider
v-model="progress"
:step="0.01"
:min="0"
:max="audio.duration"
@change="progressChange"
:format-tooltip="formatTime"
></el-slider>
</div>
<div class="audio-volume">
<div class="volume-controls" v-if="volumeStatus!=='0'">
<el-slider v-model="volume" @change="volumeChange"></el-slider>
</div>
<div class="volume-icon">
<i
class="iconfont"
v-if="volumeStatus === '0'"
@click="volumeTypeChange('1')"
></i
>
<i class="iconfont" v-else @click="volumeTypeChange('0')"
></i
>
</div>
</div>
<el-dropdown class="audio-info" @command="handleCommandMore">
<div class="foot-msg-right" @click="showSpeed = true">
<i class="iconfont foot-msg-right icon-PTgengduo"></i>
</div>
<div
class="audio-speed-popover-bg"
v-if="showSpeed"
@click="showSpeed = false"
></div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
v-for="item in speedOptions"
:key="item.value"
:class="[
'audio-speed-items',
{ actived: currentSpeed === item.value },
]"
:command="{ data: item }"
>{{ item.label }}</el-dropdown-item
>
</el-dropdown-menu>
</el-dropdown>
<audio
ref="audio"
style="width: 0; height: 0; overflow: hidden"
controls
preload="metadata"
:src="audioUrl"
@loadedmetadata="loadedmetadata"
@canplay="canplay"
@ended="ended"
@timeupdate="timeupdate"
></audio>
</div>
</template>
<-- vue -->
<script>
export default {
name: "add-summary-audio-new",
props: {
audioUrl: {
type: String,
required: true,
},
},
data() {
return {
// 播放进度
progress: 0,
// 播放速度
currentSpeed: '4',
speedOptions: [
{ value: "1", label: "2x" },
{ value: "2", label: "1.75x" },
{ value: "3", label: "1.25x" },
{ value: "4", label: "1x" },
{ value: "5", label: "0.75x" },
{ value: "6", label: "0.5x" },
],
showSpeed: false,
// 音量状态,关闭(0),开启(1)
volumeStatus: "1",
// 音量百分比
volume: 50,
// 播放状态,播放(1),暂停(0)
audioPlay: "0",
audio: {
// 是否准备就绪
isReady: false,
duration: 0,
currentTimeText: "00:00",
totalTimeText: "",
},
progressValue: 0,
};
},
computed: {
speedValues() {
const s = this.speedOptions;
const data = {};
for (let i = 0; i < s.length; i++) {
data[s[i].value] = parseFloat(s[i].label);
}
return data;
},
},
methods: {
throttle(fn, delay = 1000) {
let timer = null;
return function () {
let context = this;
let args = arguments;
if (!timer) {
fn.apply(context, args);
timer = setTimeout(function () {
timer = null;
}, delay);
}
}[代码片段](https://code.juejin.cn/pen/7121921287358234654)
},
handleCommandMore(params) {
if (this.audio.isReady) {
this.currentSpeed = params.data.value;
this.$refs.audio.playbackRate = this.speedValues[
params.data.value
];
}
},
volumeTypeChange(val) {
console.log(val);
if (!this.audio.isReady) return;
this.volumeStatus = val;
if (val === "0") {
this.$refs.audio.muted = true;
} else {
this.$refs.audio.muted = false;
}
},
volumeChange(val) {
console.log(val);
this.volume = val;
if (this.audio.isReady) {
this.$refs.audio.volume = val / 100;
}
},
changeAudioPlay() {
const res = ["1", "0"];
if (this.audio.isReady) {
this.audioPlay = res[this.audioPlay];
if (this.audioPlay === "0") {
this.$refs.audio.pause();
} else {
this.$refs.audio.play();
}
}
},
loadedmetadata(e) {
this.audio.duration = e.target.duration;
this.audio.totalTimeText = this.formatTime(e.target.duration);
this.$refs.audio.volume = 0.5;
},
canplay() {
this.audio.isReady = true;
},
// 播放完成自动停止
ended() {
this.audioPlay = "0";
},
timeupdate(e) {
this.audio.currentTimeText = this.formatTime(e.target.currentTime);
this.$nextTick(() => {
this.progress = e.target.currentTime;
// this.progress = (100 * e.target.currentTime / this.audio.duration).toFixed(2) / 1;
});
},
progressChange(value) {
// console.log("当前进度" + value)
this.$refs.audio.currentTime = value;
// this.$refs.audio.currentTime = (value / 100) * this.audio.duration;
},
formatTime(value) {
if (!value || !parseInt(value)) return "00:00";
const second = Math.floor(value % 60);
const minite = Math.floor(value / 60);
return `${minite}:${second >= 10 ? second : `0${second}`}`;
},
},
};
</script>
<-- css -->
<style lang="less" scoped>
.add-summary-audio-new {
display: flex;
height: 36px;
line-height: 36px;
background: #f8f9fa;
border-radius: 51px;
}
.audio-box {
background: rgba(247, 106, 43, 0.08);
}
.audio-progress {
width: 100%;
padding: 0 10px;
margin: 5px 0;
/deep/ .el-slider__button {
width: 12px;
height: 12px;
background-color: #f76a2b;
border: 2px solid #ffffff;
}
/deep/ .el-slider__runway {
margin-top: 10px;
background: #d0d3d6;
}
}
.audio-play-control {
.iconfont {
cursor: pointer;
}
}
.audio-download {
margin: 0 6px;
min-width: 68px;
.audio-download-i {
font-size: 12px;
color: #262626;
font-style: normal;
}
}
.audio-progress {
margin-right: 12px;
}
.audio-progress:hover{
background-color: rgba(247, 106, 43, 0.1);
border-radius: 51px;
}
.volume-controls {
margin-right: 6px;
.el-slider__bar {
transform: rotate(90deg);
}
/deep/ .el-slider__runway{
margin-top: 10px;
}
/deep/ .el-slider__button {
width: 0;
height: 0;
border: none;
}
}
.audio-info {
margin: 0 6px;
}
.audio-volume {
display: flex;
justify-content: space-around;
}
.audio-volume {
padding: 0 10px;
margin:5px 0;
line-height: 26px;
.volume-controls {
width: 0px;
// height: 50px;
transition: width 0.2s ease 0.2s;
}
}
.audio-volume:hover {
background-color: rgba(247, 106, 43, 0.1);
border-radius: 51px;
.volume-controls {
width: 80px;
}
/deep/ .el-slider__button {
width: 12px;
height: 12px;
background-color: #f76a2b;
border: 2px solid #ffffff;
}
}
.audio-speed-items {
font-size: 14px;
text-align: center;
cursor: pointer;
&.actived {
color: #F76A2B;
}
}
</style>