vue中實現彈幕功能(相似彈幕)

閒言絮語:這不剛入職新公司,接了一個項目,大體是要實現一個週年記念的app、m活動頁,統計你的線上數據blablblabl...css

需求:頁面中有一個功能,大體是獲取db中的50條數據用於彈幕展現,用戶也能夠自行發送彈幕,彈幕展現完循環展現
未命名文件 (1).png
首先,彈幕功能存在如下問題:
1.彈幕速度 位移距離
2.彈幕通道(需求中是要有3條彈幕通道)
3.當前頁面彈幕數量(渲染數量)vue

我這邊是經過vue的 過分組件 來實現彈幕功能的,由於以前在官網看到過實例,本身也用vue這麼久了,一直沒用過,此次就用來練手。數組

過分組件 顧名思義,渲染內容進行變化的時候觸發的組件,官網實例以下:
image.png瀏覽器


個人思路簡單說來: v-for 循環數組arr,內容item.msg渲染在li內部,每次維護更新這個數組arr,觸發過分組件的回調函數
回調函數很簡單,這裏不過多提起,進入前beforeEnter,進入enter,離開leaveapp

有了思路,先從一個彈幕的實現開始,彈幕初始位置應該在 left:100% 的位置,結束位置應該是 -el.offsetwidth 的位置。函數

這裏有個問題,咱們的彈幕內容是頭像+msg,若是是絕對定位的彈幕元素
在beforeEach或者初始值設定left爲100%,這裏是沒法獲取正確元素寬度
的(能夠自行查找why,這裏很少說明),因此咱們只有在彈幕進入到當前窗口
時,單獨的設置他的寬度 el.style.width = el.offsetWidth + 20 + 'px'
這裏的20px 就是咱們的頭像部分啦

image.png
彈幕進入enter階段,就開始運動了,運動到哪裏是個頭?
image.png
咱們在enter回調函數中,加入velocity動畫,(爲何用velocity?由於我看中了他的complete鉤子,能夠直接remove掉元素,這也太爽了!我能夠保證運行完的彈幕直接消失,當前頁的效率就會獲得保障!)
有了以上操做,一條彈幕就能夠完美執行了!優化


有了一條彈幕,就要考慮把彈幕一條條加入可視窗口了,定時器走起!
setInterval 每隔幾秒push一條數據到數組中,刷新瀏覽器,來看結果!動畫

結果是悲劇的... 過分組件默認是一塊兒執行的,我10秒內數組加了10條數據,結果數據一塊兒運動!這天然不是咱們想要的,要咋辦呢?我給數組的每一項綁定了一個自定義屬性
image.pngspa

image.png
而後在enter的鉤子函數中獲取到,沒一個index,定時器設置delay秒後執行動畫。
全部的彈幕就能夠完美跑起來啦!3d

最後是通道問題,需求有三條通道,我並無設置彈幕的top值,這裏大概思路就是隨機獲取一下唄,或者爲了保證間距寫一些固定值給彈幕設置top值,管道匹配上top值就ok了。

基本功能就這麼實現了。


ps:如下是這個小功能的我的思考
1.前文提到的,絕對定位元素沒法獲取正確寬度,若是不在彈幕進入的鉤子裏設置寬度,彈幕寬度會出現奇怪的現象(只根據你的msg或者頭像內容寬度展開),這是css定位的問題,有空會去了解一下

2.有關velocity的complete鉤子函數怎麼實現的?

我猜大概是監聽動畫執行完畢的事件(有兼容問題),而後封裝了一下。若是這裏要用原生,感受仍是在定時器內去監聽彈幕是否在可視窗口內。

3.自定義屬性的巧妙實用,這一步真的很nice,給每一個彈幕綁定了下標,移動的時候就可讓彈幕有序的加載。

4.彈幕速度、高度、時間等具體參數,能夠本身想象一下每條彈幕的運行軌跡,在move函數中得以實現。

5.基於問題3,考慮到是否能夠優化彈幕頁?
目前的彈幕情況是,彈幕有序加載到屏幕外側最右邊,而後每隔固定延遲開始移動,能夠保證的是每條彈幕的間隔一致,也能夠經過獲取每隔彈幕的移動距離,實現彈幕速度一致,那會不會存在彈幕層疊的狀況?理論上是會的,(3條軌道的狀況下)假如第一條彈幕是長度很是長,第二條第三條通常長度,每條之間的間隔同樣,第四條就可能會在第一條彈幕還沒消失的時候出現,致使層疊...這裏我是想把delay根據每條彈幕的寬度額外設置一下,讓每條彈幕的間隔變得不同,從而使彈幕不會層疊展現。

6.有沒有更好的方案?
設想:當前只有一個動畫,全部的彈幕都在一個容器container內,上來就根據彈幕寬度設置好每一個彈幕的間距和位置,而後整個畫布一塊兒劃過可視窗口,相似輪播圖。可是難點就是初始設置位置,以及結束的判斷,由於需求是無限重複加載彈幕...


pps:開始想到一個小小的彈幕,SO EZ,結果運行過程當中,CSS,JS,邏輯,動畫 什麼都出來了。很麻煩喲!

相關文章
相關標籤/搜索