Vue 您所在的位置:网站首页 vue自定义样式 Vue

Vue

2023-07-16 20:14| 来源: 网络整理| 查看: 265

最近遇到一个需求,需要写一个简单的音频控件:往控件传入音频url实现播放、暂停、允许拖动、显示时间等功能,由于原生audio标签样式不太好看,所以决定自己写一个。效果如下: 在这里插入图片描述

思路

把这个需求分成几个部分:左边的播放暂停按钮、右边上面的文字显示、下面的进度条。

可以把audio作为原始控件(但不在页面中显示),用自己写的控件来控制audio标签的行为动作。

1.暂停、播放按钮控制audio的play()与pause()。

2.进度条,这里可以用range来实现,修改range的样式来达到上图的效果,通过onInput和onChange来监控range拖动的变化,进而控制audio的变化(播放到指定位置)。

3.文件名字样以及右边的时间显示可以通过audio标签的duration和currentTime属性来控制。

实现

vue项目中使用了fontawesome图表库,可以根据实际自己替换。

html

html结构分为左边的图标跟右边的文字跟range控件,基本结构也比较简单。

html中必须有一个audio标签,将这个标签隐藏即可,然后用过自己写的控件来控制audio。

CSS

这里主要是对range控件的样式设置,通过input[type="range"]控制进度条的样式,通过input[type='range']::-webkit-slider-thumb控制滑块的样式。

input[type='range'] { outline: none; -webkit-appearance: none; /*清除系统默认样式*/ width: 100% !important; background: -webkit-linear-gradient(#10a9ff, #10a9ff) no-repeat, #dddddd; /*背景颜色,俩个颜色分别对应上下*/ background-size: 0% 100%; /*设置左右宽度比例,这里可以设置为拖动条属性*/ height: 2px; /*横条的高度,细的真的比较好看嗯*/ } /*拖动块的样式*/ input[type='range']::-webkit-slider-thumb { -webkit-appearance: none; /*清除系统默认样式*/ height: 10px; /*拖动块高度*/ width: 3px; /*拖动块宽度*/ background: #10a9ff; /*拖动块背景*/ } 逻辑

大体思路是:由两个icon和range控制audio,由audio控制文字的显示。

1.播放暂停图标控制audio标签播放。

audio元素有pause()和play()控制音频的暂停和播放。因此,可以对icon绑定事件控制audio的播放暂停。

// 控制音乐播放 play() { const audio = this.$refs.audio; audio.play(); this.isPlay = true; }, // 控制音乐暂停 pause() { const audio = this.$refs.audio; audio.pause(); this.isPlay = false; }

isPlay用来控制显示哪一个icon。

2.rang控制audio元素的时间进度(range拖动的时候)。

rang实际上是一个input标签,因此有onChange和onInput两个回调事件监控range相关参数的变化。audio元素有一个currentTime属性可以设置audio标签进度(即到达指定时间),可以通过监控range的变化,实时更改audio的currentTime来实现拖动改变音频进度。

注:这里将range分成了360份,后面的计算均和360相关,当然可以根据自己的需要设置。

// range--拖动进度条得到的回调 onChange() { let value = this.$refs.range.value; // 控制进度条样式 const persentage = ((value / 360) * 100).toFixed(1) + '%'; this.$refs.range.style.backgroundSize = `${persentage} 100%`; // 拖动的时候,需要跟着改变进度条样式 // 控制音频播放 const timeToGo = (value / 360) * this.totalTime; const audio = this.$refs.audio; audio.currentTime = timeToGo; } 3.audio播放的时候,控制range也跟着动。

这个发生在range控件不被人为拖动时,需要跟着audio变化(包括样式和滑块的位置)。

audio标签有方法ontimeupdate来监控audio变化,每次audio的进度变化的时候,就会执行回调。因此,可以通过绑定一个事件来实现range跟着audio变化。其中,range滑块的位置可以通过设置range的属性值value来改变,value的值在min与max之间。

// audio--进度变化的时候的回调--改变文字 update() { const audio = this.$refs.audio; const currentTime = audio.currentTime; // 当前播放时间 this.currentTime = currentTime; // 改变进度条的值 const range = this.$refs.range; range.value = ((this.currentTime / this.totalTime) * 360).toFixed(1); // 进度条的值改变的时候,颜色也跟着变化 const persentage = ((this.currentTime / this.totalTime) * 100).toFixed(1) + '%'; this.$refs.range.style.backgroundSize = `${persentage} 100%`; } 4.文件名的获取。

由于需求是传入音频url的音频播放控件,因此,可以对传入的url进行分析。

一般URL的格式是https://xxx/xxx/xxx/xxxx.mp3,可以基于/对URL分解得到数组,获取最后一个元素即为文件名。

// 获取文件名称 getFilename(url) { const arr = url.split('/'); return arr[arr.length - 1]; }, 5.当前时间与总时间的显示。

audio标签有duration和currentTime属性来获取当前音频播放进度以及总时间(单位是秒)。获取到当前时间以及播放总时间后,进行格式处理之后就可以绑定到相关的位置上。

{{ audioName==null ? "未知": audioName}} {{ formatCurrentTime }} / {{ formatTotalTime }}

formatCurrentTime和formatTotalTime是由currentTime和totalTime通过计算属性返回的,下面只分析currentTime和totalTime的获取。

// audio--进度变化的时候的回调--改变文字 update() { const audio = this.$refs.audio const currentTime = audio.currentTime // 当前播放时间 this.currentTime = currentTime },

总时间在音频加载完毕后就进行记录,通过绑定audio的onCanplay回调来实现。

loadingFinish() { const totalTime = this.$refs.audio.duration this.totalTime = totalTime } 6.prop设置。

传入一个音频URL,用于显示文件名以及作为audio的音源链接。

最后

当然,样式可以更"花里胡哨" 。主要是了解了audio标签的onUpdatetime()回调、onCanplay()回调;range的value属性、onChange()回调、onInput()回调。功能也可以进一步扩展,后面再添加吧~

完整代码 {{ audioName==null ? "未知": audioName}} {{ formatCurrentTime }} / {{ formatTotalTime }} export default { name: 'AudioPlayer', components: {}, props: { audioURL: { type: String, default: '../未知', }, }, data() { return { isPlay: false, // 控制icon切换 totalTime: 0, // 播放总时间--秒 currentTime: 0, // 当前播放时间--秒 } }, computed: { formatTotalTime() { return this.formatTime(this.totalTime) }, formatCurrentTime() { return this.formatTime(this.currentTime) }, // 音频名称 audioName() { return this.getFilename(this.audioURL) }, }, mounted() { this.$refs.audio.src = this.audioURL // 将range位置归0--如果不使用这个的话,设置了value之后没有用= =郁闷 setTimeout(() => { this.$refs.range.value = 0 }, 1) }, methods: { // 控制音乐播放 play() { const audio = this.$refs.audio audio.play() this.isPlay = true }, // 控制音乐暂停 pause() { const audio = this.$refs.audio audio.pause() this.isPlay = false }, // 音乐缓存完毕,获取时间 loadingFinish() { const totalTime = this.$refs.audio.duration this.totalTime = totalTime }, // range--拖动进度条得到的回调 onChange() { let value = this.$refs.range.value const persentage = ((value / 360) * 100).toFixed(1) + '%' this.$refs.range.style.backgroundSize = `${persentage} 100%` // 控制音频播放 const timeToGo = (value / 360) * this.totalTime const audio = this.$refs.audio audio.currentTime = timeToGo }, // audio--进度变化的时候的回调--改变文字 update() { const audio = this.$refs.audio const currentTime = audio.currentTime // 当前播放时间 this.currentTime = currentTime // 改变进度条的值 const range = this.$refs.range range.value = ((this.currentTime / this.totalTime) * 360).toFixed(1) // 进度条的值改变的时候,颜色也跟着变化 const persentage = ((this.currentTime / this.totalTime) * 100).toFixed(1) + '%' this.$refs.range.style.backgroundSize = `${persentage} 100%` }, //辅助函数,将秒变成分秒的形式--用在计算属性中 formatTime(value) { let second = 0 let minute = 0 minute = parseInt(value / 60) second = parseInt(value % 60) // 补0 minute = minute padding: 8px 16px; width: 100%; background: #f5f6f8; border-radius: 2px; display: flex; } .left { margin-right: 16px; } // 播放暂停按钮 .icon { display: inline-block; width: 28px; height: 28px; border: 2px solid #10a9ff; border-radius: 50%; text-align: center; font-size: 16px; line-height: 28px; color: $base-color-blue; } .icon:hover { cursor: pointer; } .play-icon { position: relative; left: 2px; } .flex-between { display: flex; justify-content: space-between; align-content: center; } .right { flex: 1; } .words { margin-bottom: -1px; } .name { font-size: 14px; color: #333333; line-height: 14px; } .time { font-size: 14px; color: #666666; line-height: 14px; } // 控件 input[type='range'] { outline: none; -webkit-appearance: none; /*清除系统默认样式*/ width: 100% !important; background: -webkit-linear-gradient(#10a9ff, #10a9ff) no-repeat, #dddddd; /*背景颜色,俩个颜色分别对应上下*/ background-size: 0% 100%; /*设置左右宽度比例,这里可以设置为拖动条属性*/ height: 2px; /*横条的高度,细的真的比较好看嗯*/ } /*拖动块的样式*/ input[type='range']::-webkit-slider-thumb { -webkit-appearance: none; /*清除系统默认样式*/ height: 10px; /*拖动块高度*/ width: 3px; /*拖动块宽度*/ background: #10a9ff; /*拖动块背景*/ }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有