vue圆形进度条音乐播放
紫菀檀ss 人气:0最近在使用vue做仿网易云音乐的项目,遇到了圆形进度条实现音乐播放的功能,所以我在这里总结一下,分享给大家我的实现方法。我这里主要是通过SVG的方式实现的。
效果图:
实现过程
一、实现步骤
- 圆形进度条的实现
- 音乐播放/暂停的控制
二、步骤分解
这里先放一下 audio标签引入音频文件的代码:
<audio src="/static/audios/周兴哲 - 你,好不好?.mp3" @timeupdate="timeupdate" id="audio" @ended="ended"></audio> /* timeupdate() 方法 实时获取 音频当前播放时长 ended() 方法 播放结束的时候触发 */ // 实时获取音频当前播放时长 timeupdate(e) { // console.log("e===>", e.target.currentTime); this.current = e.target.currentTime; let duration = document.getElementsByTagName("audio")[0].duration; let percent = Math.min(1, this.current / duration); this.dashOffset = (1 - percent) * this.dashArray; }, ended() { console.log("播放结束~~~"); this.isStatus = false; // 初始化 圆形进度条的周长 let circleWidth = document.getElementById("progressCircle").offsetWidth; this.dashArray = Math.PI * circleWidth; this.dashOffset = Math.PI * circleWidth; },
1. 圆形进度条的实现
这里通过SVG画两个一模一样的圆,设置一定的宽度,然后第二个圆使用stroke-dasharray
和stroke-dashoffset
来动态控制进度变化情况。stroke-dashoffset
的变化情况要结合音乐的时长来设置。
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" id="mySvg"> <circle class="progress-background" cx="50%" cy="50%" r="50%" fill="transparent" /> <circle class="progress-bar" cx="50%" cy="50%" r="50%" fill="transparent" :stroke-dasharray="dashArray" :stroke-dashoffset="dashOffset" /> </svg> computed: { // 实时监听播放进度 getDashOffset() { let percent = 0; if (document.getElementsByTagName("audio")[0]) { // 计算播放进度比例 let duration = document.getElementsByTagName("audio")[0].duration; percent = Math.min(1, this.current / duration); this.dashOffset = (1 - percent) * this.dashArray; } else { this.dashOffset = (1 - 0) * this.dashArray; } } }, mounted() { this.$nextTick(() => { // 初始化圆角周长 let circleWidth = document.getElementById("progressCircle").offsetWidth; this.dashArray = Math.PI * circleWidth; this.dashOffset = Math.PI * circleWidth; }); }
2. 音乐播放/暂停的控制
音乐的暂停和播放状态可以通过document.getElementById("audio").paused
来判断,如果返回false则说明当前是播放状态,我们需要触发 document.getElementById("audio").pause()
方法实现暂停操作,反之,触发document.getElementById("audio").play()
方法实现播放操作。
// 操作音乐播放/暂停 let audio = document.getElementById("audio"); console.log("this.audio.paused===>", audio.paused); if (audio.paused) { audio.play(); } else { audio.pause(); }
下面方法全部的代码,大家可直接复制到自己的编辑器中运行(记得修改音频路径)
<template> <div class="playmusic"> <div class="bottom-music"> <div class="music-lt"> <div class="lt-avator"> <img src="/static/img/avator.jpg" alt /> </div> <div class="lt-title"> <span class="title">你,好不好?</span> <span class="name">周兴哲</span> </div> </div> <div class="music-rt"> <div class="progress-circle" id="progressCircle" @click="operation"> <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" id="mySvg"> <circle class="progress-background" cx="50%" cy="50%" r="50%" fill="transparent" /> <circle class="progress-bar" cx="50%" cy="50%" r="50%" fill="transparent" :stroke-dasharray="dashArray" :stroke-dashoffset="dashOffset" /> </svg> <span :class="isStatus?'iconfont icon-bofang3 icons':'iconfont icon-bofang2 icons icons1'" ></span> </div> <span class="iconfont icon-yinleliebiao menu"></span> <audio src="/static/audios/周兴哲 - 你,好不好?.mp3" @timeupdate="timeupdate" id="audio" @ended="ended"></audio> </div> </div> </div> </template> <script> export default { data() { return { dashArray: 0, current: 0, dashOffset: 0, isStatus: false // 播放状态 false 暂停 true 播放 }; }, computed: { // 实时监听播放进度条 getDashOffset() { let percent = 0; if (document.getElementsByTagName("audio")[0]) { // 计算播放进度比例 let duration = document.getElementsByTagName("audio")[0].duration; percent = Math.min(1, this.current / duration); this.dashOffset = (1 - percent) * this.dashArray; } else { this.dashOffset = (1 - 0) * this.dashArray; } } }, methods: { // 实时获取音频当前播放时长 timeupdate(e) { // console.log("e===>", e.target.currentTime); this.current = e.target.currentTime; let duration = document.getElementsByTagName("audio")[0].duration; let percent = Math.min(1, this.current / duration); this.dashOffset = (1 - percent) * this.dashArray; }, ended() { console.log("播放结束~~~"); this.isStatus = false; // 初始化 圆形进度条的周长 let circleWidth = document.getElementById("progressCircle").offsetWidth; this.dashArray = Math.PI * circleWidth; this.dashOffset = Math.PI * circleWidth; }, // 操作音乐播放/暂停 operation() { console.log("播放/暂停音乐"); let audio = document.getElementById("audio"); console.log("this.audio.paused===>", audio.paused); if (audio.paused) { audio.play(); this.isStatus = true; } else { audio.pause(); this.isStatus = false; } } }, mounted() { this.$nextTick(() => { // 初始化圆的周长 let circleWidth = document.getElementById("progressCircle").offsetWidth; this.dashArray = Math.PI * circleWidth; this.dashOffset = Math.PI * circleWidth; }); } }; </script> <style lang="css" scoped> .font { font-family: PingFangSC-Regular, PingFang SC; font-weight: 400; } .playmusic { position: relative; height: 100vh; width: 100%; } .playmusic .bottom-music { box-sizing: border-box; padding: 0 0.64rem; z-index: 999; box-shadow: 5px 5px 5px 5px #efefef, -5px 5px 5px 5px rgba(255, 255, 255, 0.5); } .playmusic .bottom-music { height: 3.41333333rem; width: 100%; position: fixed; left: 0; bottom: 0; display: flex; justify-content: space-around; align-items: center; background-color: #ffffff; } .playmusic .bottom-music .music-lt { flex: 1; display: flex; align-items: center; justify-content: start; width: 70%; overflow: hidden; } .playmusic .bottom-music .music-lt .lt-avator { width: 2.13333333rem; height: 2.13333333rem; border-radius: 50%; overflow: hidden; } .playmusic .bottom-music .music-lt .lt-avator img { width: 100%; height: 100%; display: block; } .playmusic .bottom-music .music-lt .lt-title { padding: 0 0.42666667rem; width: 80%; } .playmusic .bottom-music .music-lt .lt-title span { display: block; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-family: PingFangSC-Regular, PingFang SC; font-weight: 400; } .playmusic .bottom-music .music-lt .lt-title .title { font-size: 0.59733333rem; font-weight: 600; color: #333; } .playmusic .bottom-music .music-lt .lt-title .name { font-size: 0.46933333rem; color: #666; } .playmusic .bottom-music .music-rt { display: flex; justify-content: end; align-items: center; } .playmusic .bottom-music .music-rt .progress-circle { width: 1.92rem; height: 1.92rem; position: relative; } .playmusic .bottom-music .music-rt .progress-circle circle { stroke-width: 0.14933333rem; transform-origin: center; } .playmusic .bottom-music .music-rt .progress-circle .progress-background { transform: scale(0.9); stroke: rgba(212, 68, 57, 0.5); } .playmusic .bottom-music .music-rt .progress-circle .progress-bar { transform: scale(0.9) rotate(-90deg); stroke: #d44439; } .playmusic .bottom-music .music-rt .progress-circle .icons { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: #d44439; } .playmusic .bottom-music .music-rt .progress-circle .icons { font-size: 1.17333333rem; } .playmusic .bottom-music .music-rt .progress-circle .icons1 { font-size: 0.96rem; } .playmusic .bottom-music .music-rt .menu { font-size: 1.70666667rem; color: #d44439; font-weight: 500; } .playmusic .bottom-music .music-rt .menu { padding-left: 0.85333333rem; } </style>
加载全部内容