vue使用SVG實現圓形進度條音樂播放
最近在使用vue做仿網易云音樂的項目,遇到了圓形進度條實現音樂播放的功能,所以我在這里總結一下,分享給大家我的實現方法。我這里主要是通過SVG的方式實現的。
效果圖:
實現過程
一、實現步驟
- 圓形進度條的實現
- 音樂播放/暫停的控制
二、步驟分解
這里先放一下 audio標簽引入音頻文件的代碼:
<audio src="/static/audios/周興哲 - 你,好不好?.mp3" @timeupdate="timeupdate" id="audio" @ended="ended"></audio> /* ?? ?timeupdate() 方法 ? 實時獲取 音頻當前播放時長 ?? ?ended() 方法 ? 播放結束的時候觸發(fā) */ // 實時獲取音頻當前播放時長 ? ? 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
來動態(tài)控制進度變化情況。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: { ?? ??? ? ? ?// 實時監(jiān)聽播放進度 ?? ??? ? ? ?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. 音樂播放/暫停的控制
音樂的暫停和播放狀態(tài)可以通過document.getElementById("audio").paused
來判斷,如果返回false則說明當前是播放狀態(tài),我們需要觸發(fā) document.getElementById("audio").pause()
方法實現暫停操作,反之,觸發(fā)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 // 播放狀態(tài) ?false 暫停 ?true 播放 ? ? }; ? }, ? computed: { ? ? // 實時監(jiān)聽播放進度條 ? ? 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>
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Vue組件化(ref,props,?mixin,.插件)詳解
這篇文章主要介紹了Vue組件化(ref,?props,?mixin,?插件)的相關知識,包括ref屬性,props配置項及mixin混入的方式,本文通過示例代碼多種方式相結合給大家介紹的非常詳細,需要的朋友可以參考下2022-05-05vue-cli 腳手架基于Nightwatch的端到端測試環(huán)境的過程
這篇文章主要介紹了vue-cli 腳手架基于Nightwatch的端到端測試環(huán)境的過程,需要的朋友可以參考下2018-09-09