基于VUE和JS手写的移动端H5自定义音乐播放器(直线进度条和圆形滚动进度条)
1. 先上效果图,可以嵌合在H5移动端页面,可拖拽点击颜色进度条的小白色圆圈快进~下面就是圆形的进度条哦~(请尊重劳动成果,转载请注出处~)P.S(在这里说下圆形进度条的效果,一开始也是用canvas,但是发现canvas不支持淘宝适配方案,于是想着自己写一个,思路是控制圆边的显示。后来忽然看到园友--JR93的一篇文章思路一下子彻底就打通了。用度数逐步增加来控制圆边的显示比控制周长来得好...
·
1. 先上效果图,可以嵌合在H5移动端页面,可拖拽点击颜色进度条的小白色圆圈快进~下面就是圆形的进度条哦~(请尊重劳动成果,转载请注出处~)
P.S(在这里说下圆形进度条的效果,一开始也是用canvas,但是发现canvas不支持淘宝适配方案,于是想着自己写一个,思路是控制圆边的显示。后来忽然看到园友-- JR93 的一篇文章思路一下子彻底就打通了。用度数逐步增加来控制圆边的显示比控制周长来得好。在此感谢)
2. HTML代码部分
<template>
<div>
<div class="bar">
<div class="progressbar" @click="playMusic" ref="runfatbar">
<div class="greenbar" ref="runbar">
<span class="yuan" draggable="true"></span>
</div>
</div>
</div>
<div class="time-text">{{cTime}}</div>
<div class="right-time time-text">{{dTime}}</div>
<div class="audio-btn">
<i class="icon icon-left" @click="switchAudio('top')"></i>
<i :class="play ? 'icon icon-stop' : 'icon icon-play'" @click="audioState"></i>
<i class="icon icon-right2" @click="switchAudio('bottom')"></i>
</div>
<div>
<audio ref="player" :src="audioHttp">
</audio>
</div>
<!-- 这里是圆形进度条 -->
<div class="circleProgress_wrapper">
<div class="wrapper right">
<div class="circleProgress rightcircle" ref="yuanright"></div>
</div>
<div class="wrapper left">
<div class="circleProgress leftcircle" ref="yuanleft"></div>
</div>
</div>
</div>
</template>
3. SCSS部分 P.S(这里的icon用的是scss特点,可以直接在HTML里面用img标签,只是我习惯这样写,因为后期判断切换方便。关于deg度数的兼容性可以自行百度泳-wekbit-之类的解决)
.circleProgress_wrapper{
width: px2rem(80);
height: px2rem(80);
margin: px2rem(50) auto;
position: relative;
border:1px solid #ddd;
}
.wrapper{
width: px2rem(40);
height: px2rem(80);
position: absolute;
top:0;
overflow: hidden;
}
.right{
right:0;
}
.left{
left:0;
}
.circleProgress{
width: px2rem(70);
height: px2rem(70);
border:px2rem(5) solid transparent;
border-radius: 50%;
position: absolute;
top:0;
}
.rightcircle{
border-top:px2rem(5) solid #1296db;
border-right:px2rem(5) solid #1296db;
right:0;
transform: rotate(-135deg);
display: none;
}
.leftcircle{
border-bottom:px2rem(5) solid #1296db;
border-left:px2rem(5) solid #1296db;
left:0;
transform: rotate(-135deg);
display: none;
}
.bar {
width: 100%;
height: px2rem(30);
line-height: px2rem(30);
.progressbar {
width: 100%;
height: px2rem(10);
background-color: #999999;
margin-top: px2rem(10);
border-radius: px2rem(30);
position: relative;
}
.greenbar {
width: 0%;
height: px2rem(10);
border-radius: px2rem(30);
position: absolute;
top: 0;
left: 0;
background-color: #1296db;
.yuan {
display: inline-block;
padding: px2rem(10);
background-color: #ffffff;
border-radius: 50%;
position: absolute;
top: px2rem(-5);
right: px2rem(-20);
}
}
}
.time-text {
display: inline-block;
width: 50%;
padding: 0 px2rem(30);
box-sizing: border-box;
}
.right-time {
text-align: right;
}
.audio-btn {
width: 100%;
text-align: center;
}
.icon {
@include size(80, 80);
display: inline-block;
margin-right: px2rem(20);
vertical-align: middle;
$icon-list: right2 left play stop;
@each $icon in $icon-list {
&.icon-#{$icon} {
@include background-cover("icon-#{$icon}.png");
}
}
}
4. JS部分
export default {
name: 'music-view',
components: {
},
props: {
type: '',
},
data () {
return {
cTime: '00:00', // 已播放时间
dTime: '00:00', // 总播放时间
play: false, // 播放暂停按钮
audioHttp: 'http://up.mcyt.net/?down/46426.mp3', // 音频链接
}
},
mounted () {
const music = this.$refs.player // 音频所在对象
const musicBar = this.$refs.runbar // 颜色进度条所在对象
const musicWidth = this.$refs.runfatbar.offsetWidth // 底部进度条总宽
const rightCircle = this.$refs.yuanright.style // 圆形滚动进度条右边
const leftCircle = this.$refs.yuanleft.style // 圆形滚动进度条左边
// 获得音频加载完成可播放时的处理
music.addEventListener('canplay', () => {
const musicTime = music.duration // 获得音频时长
const branch = Math.floor(musicTime / 60) // 计算音频分钟
const second = Math.ceil(musicTime % 60) // 计算音频秒
if (branch < 10 && second < 10) { // 四种情况判断音频总时间
this.dTime = `0${branch}:0${second}`
} else if (branch < 10) {
this.dTime = `0${branch}:${second}`
} else if (second < 10) {
this.dTime = `${branch}:0${second}`
} else {
this.dTime = `${branch}:${second}`
}
})
// 获得音频正在播放时的处理
music.addEventListener('timeupdate', () => {
const musicTime = music.duration // 获得音频时长
const circleTime = musicTime / 360 // 计算总时长占据360度每一度的比例
const stopTime = music.currentTime // 获得已播放的音频时长
const rightDeg = -135 + (stopTime / circleTime) // 计算出当前旋转度数
if (rightDeg < 45) { // 如果当前度数小于45就证明在右边
rightCircle.display = 'block' // 显示右边圆
rightCircle.transform = `rotate(${rightDeg}deg)` // 赋值给CSS右边圆旋转度数
leftCircle.display = 'none' // 隐藏左边园(预防切歌的时候右边已清除)
} else if (rightDeg === 45 || rightDeg > 45) { // 如果当前度数等于或大于45就证明在左边
rightCircle.display = 'block' // 显示右边圆(预防直接点击快进的时候右边无显示)
leftCircle.display = 'block' // 显示左边圆
rightCircle.transform = 'rotate(45deg)' // 固定右边旋转度数
const leftDeg = -135 + ((stopTime - (musicTime / 2)) / circleTime) // 计算出当前左边旋转度数
leftCircle.transform = `rotate(${leftDeg}deg)` // 赋值给CSS右边圆旋转度数
}
musicBar.style.width = `${(stopTime / musicTime) * 100}%` // 计算进度条所在比例宽度
const branch = Math.floor(stopTime / 60) // 计算已播放的音频分钟
const second = Math.floor(stopTime % 60) // 计算已播放的音频秒
if (branch < 10 && second < 10) { // 四种情况判断显示音频以播放时间
this.cTime = `0${branch}:0${second}`
} else if (branch < 10) {
this.cTime = `0${branch}:${second}`
} else if (second < 10) {
this.cTime = `${branch}:0${second}`
} else {
this.cTime = `${branch}:${second}`
}
})
// 监听颜色进度条是否触摸拖动
musicBar.addEventListener('touchmove', (event) => {
const events = event.targetTouches[0].pageX // 获得触摸拖动的距离
musicBar.style.width = `${(events / musicWidth) * 100}%` // 计算进度条所在比例宽度
music.pause() // 触摸拖动时停止播放
})
// 监听颜色进度条是否触摸拖动结束
musicBar.addEventListener('touchend', () => {
const touwidth = (musicBar.offsetWidth / musicWidth) // 计算进度条所在比例
music.currentTime = music.duration * touwidth // 通过所在比例赋值给音频应在的播放时间
music.play() // 根据播放时间开始播放
this.play = true // 更改播放暂停按钮为播放
})
// 这里顺便写的,适用于PC端。鼠标事件
// musicBar.addEventListener('drag', (e) => {
// const events = e.pageX
// musicBar.style.width = `${(events / musicWidth) * 100}%`
// })
// musicBar.addEventListener('dragend', (e) => {
// const events = e.pageX
// musicBar.style.width = `${(events / musicWidth) * 100}%`
// this.playMusic()
// })
},
computed: {
},
methods: {
// 点击进度条事件
playMusic (e) {
const music = this.$refs.player // 音频所在对象
const barWidth = e.pageX / this.$refs.runfatbar.offsetWidth // 计算点击位置相对父元素总宽的比例
this.$refs.runbar.style.width = `${barWidth * 100}%` // 进度条应所在的比例总宽
music.currentTime = music.duration * barWidth // 计算点击时应播放所在的时间
music.play() // 播放音频
this.play = true // 更改播放暂停按钮为播放
},
// 点击播放暂停按钮时间
audioState () {
this.play = !this.play // 更改播放暂停按钮状态
const music = this.$refs.player // 音频所在对象
if (this.play) {
music.play() // 播放音乐
} else {
music.pause() // 暂停音乐
}
},
// 切换歌曲按钮
switchAudio (value) {
if (value === 'top') {
this.audioHttp = 'http://mp3.henduoge.com/mp3/2018-04-19/1524135488.mp3'
} else if (value === 'bottom') {
this.audioHttp = 'http://mp3.henduoge.com/mp3/2018-04-20/1524234022.mp3'
}
this.play = false // 播放按钮为暂停
this.$refs.runbar.style.width = 0 // 清空颜色进度条
this.$refs.yuanright.style.display = 'none' // 清空圆形颜色进度条
this.$refs.yuanleft.style.display = 'none' // 清空圆形颜色进度条
},
},
}
更多推荐
已为社区贡献10条内容
所有评论(0)