對Vue.js音樂播放器的總結(jié)。(七)

這章是播放器的重頭戲-------音樂播放器的設(shè)置,學(xué)到了很多

基礎(chǔ)組件,像songList這種被多次復(fù)用的組件,不寫邏輯代碼,它只派發(fā)事件?。?!
寫在前面:父組件向子組件傳遞的prop是可以實時變化的,子組件接受到的prop也是實時變化的,props是不會被子組件修改的。動畫結(jié)束之后記得清除!:class="{'clsname': xxx}" class綁定的不一定是一個對象,還可以是一個計算屬性返回值

1:

對播放器的樣式進行分析,先暫時跳過把

2:

vuex相關(guān),跳過

3:

播放器組件dom和基本樣式,跳過

4:

vue的動畫效果! create-keyframe-animation
在vue中使用動畫,在外層增加一個transition標(biāo)簽,一般定義兩個屬性,一個是enter-active(leave-active)和enter(leave-to),他們都是在元素消失或者出現(xiàn)這一過程的狀態(tài)。transition是過渡,定義對什么屬性進行過渡效果,時間為幾秒。(還可以自定義緩動曲線,即bezier曲線,控制在0.4s時間內(nèi)動畫的速度快慢)

動畫效果

這張圖即代表在normalplayer進入的時候,在0.4s時間內(nèi)漸顯,他的top向下移動100px,bottom向上移動100px

當(dāng)然,我們還不滿足這么簡單的動畫

飛入動畫

像上圖,我們要實現(xiàn)miniPlayer的小圓圈飛向大的圓圈的動畫(沒有視頻。。大家發(fā)揮自己的想象力,233333)
相信大家第一個想到的都是用css里面的關(guān)鍵幀動畫@key-frame吧。具體的css我就不說了,大家可以自己去百度一下。如果用純css來寫 我們可能這樣寫
css

但是這里就涉及到一個問題了,你怎么知道大圓圈中心的位置是多少?在不同手機上,不同圓圈的中心點不同的呀。所以我們需要用js來生成css代碼,這里就要用到幾個關(guān)鍵知識:
1.create-keyframe-animation動畫庫
create-keyframe-animation就是一個通過js創(chuàng)建css動畫的庫,當(dāng)動畫的坐標(biāo)需要計算時,可以用到這個庫
2.vue中transition的js鉤子
注意:enter和leave中回調(diào)函數(shù)是必須的!!否則他們會被同步調(diào)用!
(兩項都建議大家去看官方文檔,挺簡單的)

js鉤子

我們?yōu)槊總€鉤子觸發(fā)一個函數(shù)
enter周期的時候注冊,記得結(jié)束時調(diào)用回調(diào)函數(shù),這個動畫的意思是一開始wrapper在左下角小圓圈的位置,60%的時候回到中間,100%的時候變回原形,中間有個彈性變小的過程

enter

afterEnter的時候要清空動畫,并且取消注冊動畫

afterEnter

leave的動畫稍微簡單,不需要用到create-keyframe-animation

LeaveAndAfterleave

5:

歌曲播放功能實現(xiàn)

具體思路如下:
1.為audio標(biāo)簽制定src來源
2.調(diào)用audio.play方法播放

涉及到的問題和解決方法如下:
1.為src用v-bind綁定歌曲來源

audio

2.什么時候開始播放?最好的時機是currentSong改變的時候,因為當(dāng)你點擊songList或者其它按鈕的時候,都是改變當(dāng)前的currentSong,所以我們就要watch currentSong。
image.png

但是這里會有一個bug當(dāng)你調(diào)用play的時候,dom還沒有ready渲染好,所以會報錯,我們需要在nextTick再去操作dom

實現(xiàn)上面幾步后,現(xiàn)在已經(jīng)可以播放歌曲了。那我們又遇到一個難題,怎么讓它停下來?
之前在vuex中設(shè)置過playing狀態(tài),當(dāng)它為true時,我們調(diào)用this.$refs.audio.play(),否則調(diào)用this.$refs.audio.pause()。但是緊接著又來了,你怎么設(shè)置playing狀態(tài)?當(dāng)然是通過暫停播放按鈕啦,給它添加一個click事件,調(diào)用mutation方法,同時要改變它的class,對了normalPlayer和miniPlayer是一樣的!

playBtn
togglePlay
className

好啦,現(xiàn)在我們大功告成,已經(jīng)可以實現(xiàn)基本的播放暫停操作了。然后我們還要讓這個cd旋轉(zhuǎn)起來! 用到css的animation動畫,跟之前的keyframe是一樣滴,當(dāng)playing的時候給它加上play類名,反之則加上pause類名

image.png
rotate
css

6:

接下來我們來實現(xiàn)歌曲的前進后退功能。
實現(xiàn)該功能,本質(zhì)上是改變currentSong,在vuex中currentSong是通過playlist和currentIndex得到的(getter也能充當(dāng)計算屬性)

currentSong

那么,我們給前進和后退按鈕各自綁定一個click事件,改變currentSong,注意控制邊界條件,如果是上一首歌是暫停,點擊下一首歌默認(rèn)播放。if(!this.songReady) return}這句話是干嘛的等會會講)

click事件
next函數(shù)

好啦,現(xiàn)在是真ojbk了。你的播放器現(xiàn)在有大概的雛形了,但是身為一個有節(jié)操的程序員,程序中發(fā)現(xiàn)了錯誤就要及時修改喲,比如當(dāng)你快速切換下一首歌的時候,dom有時候還沒渲染好會出現(xiàn)這樣一個錯誤


error

我們當(dāng)然要fix這個錯誤,audio標(biāo)簽在準(zhǔn)備好播放的時候,會觸發(fā)一個canplay事件,出錯的時候會觸發(fā)error事件(具體事件請看文章最下方),我們對這兩個事件進行操作。
添加一個songReady標(biāo)志位,默認(rèn)為false,在ready的時候置為true

songReady

再結(jié)合上面的next函數(shù)看看,你是不是就理解了呢?

7:

接下來讓我們來試試修改當(dāng)前時間吧!
audio標(biāo)簽播放的時候會實時觸發(fā)一個很重要的事件timeupdate,一般控制歌曲播放都是靠它。e.target是audio標(biāo)簽。而e.target.currentTime是指當(dāng)前播放的時間,它是可讀寫的,你可以直接修改它。

這個事件觸發(fā)的時候我們給它設(shè)置一個函數(shù),在這個函數(shù)中我們獲取兩個東西:currentTime和totalTime。因為這兩個都是時間戳,所以還需要定義一個format函數(shù)格式化我們得到的時間戳

e.target
event
image.png

8:

進度條組件百分比播放實現(xiàn)
思考一下,這樣的功能要怎么實現(xiàn)呢? 我們可以通過currentTime / totalTime 獲得一個百分比,然后讓進度條的寬度隨著這個百分比的增大而增大
我們來寫一個progressBar組件,它接受一個percent props,progress的長度就是經(jīng)過了多少時間,progressBtn就是那個小圓頭,BallWidth就是小圓球的寬度。這里要注意這篇文章開頭寫的一句話:props是實時改變的。 我們來watch props的變化

progressBar
watch

9:

進度條拖拽功能實現(xiàn)
因為audio.duration是一個可改的變量。你在子組件拖動進度條的時候,不止要改變progress的寬度,同時還會有一個新的percent,再touchend的時候你傳到父組件去修改audio.duration。點擊進度條的時候如果用的是click事件,獲得偏移量要通過e.offsetX。如果是touchstart事件就通過e.touches[0].pageX獲取

touch
offset

這里還會有一個小bug,如果你不加this.touch.isTouch這個標(biāo)志位的話,你在滑動的時候,percent也在改變,這時候還會調(diào)用watch里面的方法設(shè)置offsetWidth。所以我們增加一個標(biāo)志位來判斷進度條長度的變化是不是由拖拽產(chǎn)生的。

10:

圓形進度條的實現(xiàn)(svg不會。。跳過。。)

11:

設(shè)置歌曲播放模式,需要注意的點是nextMode = (this.mode+1) %3。注意這個的打亂算法,改變歌曲順序的時候注意this.currentSong是靠this.currentIndex和this.playlist獲得的,如果只是打亂playlist的話,currentSong就會變化,所以要同時改變playlist和currentIndex

shuffle
image.png
image.png

12:

完成剩下的進度條功能,拉到最后的時候拉到下一首歌,需要觸發(fā)ended事件,如果是loop模式,在播放完之后要讓audio.currentTime = 0

loop

回到musicList組件,完成隨機播放全部的按鈕,點擊這個之后,應(yīng)該改變vuex的mode,playing,觸發(fā)的mutation有點多,就把它封裝到action里面去

randomPlay
action

但是還會有一個bug,當(dāng)你是隨機播放的時候,點擊music-list里面的歌,它彈出來的跟你的預(yù)料的不同

為什么呢? 是因為我們點擊music-list的時候,會調(diào)用我們之前寫的action,然后我踩了一個坑。。。

這個坑以后一定要注意了?。。?/h1>

在shuffle函數(shù)里面,我設(shè)置了newArr = arr 這是一個淺拷貝,是地址引用,這樣你對newArr做修改 arr也會改變,所以在調(diào)用之前的action的時候,傳入的shuffle過的數(shù)組!?。?!同時,你點擊隨機播放全部的時候,player組件里面對mode的watch也會生效,就會再次mutation一個playlist

shuffle
之前寫的action

audio標(biāo)簽事件如下:


audio標(biāo)簽事件
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容