Vue 實現彈幕效果

這兩天又看到有人問 Vue 如何作彈幕效果css

正好我過年的時候作了個活動,其中用戶能夠搖籤,而後 C 位飄屏展現。html

Vue 版本效果地址:https://www.lilnong.top/static/html/vue-bullet-biubiubiu.html
網上原生版本:https://www.lilnong.top/stati...前端

image.png

實現原理

彈幕動畫效果

動畫效果其實很簡單,從右到左vue

通常來講咱們認知的動畫流暢度順序是 css(transform) > css(left) > js微信

實現 css 的動畫效果的方式

實現起來有兩種方案動畫

  1. transtion 狀態 A 到狀態 B 使用過渡效果
    這個重點是須要觸發狀態變化,因此咱們能夠考慮 push 以後 $nextTick 中再改變狀態。
  2. animation 元素作動畫。
    這個就比較簡單了,他是單指元素動畫

transform + animation

咱們先來看看 css 的 transform 如何實現動畫效果。this

@keyframes right2left {
    0% {transform: translate(100vw)}
    100% {transform: translate(-100%);}
}

由於 translate 的 % 是基於當前元素的,因此咱們能夠設置開始位置在 100vw(正好在右邊屏幕外),結束位置在 -100%(正好把本身都挪到左邊屏幕外)spa

left + animation

@keyframes right2left {
    0% {left: 100%}
    100% {left: -100%}
}

left 的 % 是基於父級的 width,因此這裏開始位置能夠設置 100%,結束位置不太好控制 -100%設計

彈幕隊列設計

由於個人需求是當前登陸用戶發出的會在 C 位顯示,因此我把他設計成了三個隊列code

  1. 普通的彈幕隊列,裏面用來存放其餘用戶發的
  2. c 位彈幕隊列,用來存放當前用戶發的
  3. 頁面中顯示的彈幕隊列
// item 是當前要顯示的彈幕
var item = null;
// 判斷一下是不是 c 位,c 位的話要先排查 c 位彈幕隊列
if(this.idx == 3){
    // c 位
    item = this.clist.shift();
}
// 若是說沒有要顯示的彈幕,那麼取普通彈幕隊列的彈幕
if(!item){
    item = this.list.shift();
}

if(item){
    // 若是有彈幕,那麼放到顯示隊列中
    item.line = this.idx;
    this.idx = (this.idx % 5 + 1);
    this.bulletlist.push(item)
}else{
    // 若是沒有彈幕,那麼排查一下有沒有 c位 彈幕隊列
    // 由於個人彈幕作了循環,因此不太可能出現這種狀況
    if(this.clist.length){
        item = this.clist.shift();
        item.line = 3;
        this.idx = 3;
        this.bulletlist.push(item)
    }
}

動畫開始與結束邏輯

動畫開始由於我使用的是 animation,那麼當 DOM 顯示在頁面中他就會執行動畫。
動畫結束是監視 animationend 的回調,由於個人動畫時長是固定,因此每次都移除第一個 DOM 便可。

若是是 transtion 應該怎麼作?

transtion 也有對應的結束事件 transtionend

可是開始比較坑,他須要的是兩幀。這裏咱們要依賴 $nextTick 來實現

彈幕碰撞等問題

設置五條航道,每 1000ms 渲染一個彈幕,這樣的話就能夠錯開行。

並且由於動畫是固定時長,因此能夠人爲控制一行只有一個。

微信公衆號:前端linong

歡迎你們關注個人公衆號。有疑問也能夠加個人微信前端交流羣。
clipboard.png

相關文章
相關標籤/搜索