使用transition實(shí)現(xiàn)彈幕滾動(dòng)效果

???????想要實(shí)現(xiàn)比較理想的彈幕滾動(dòng)效果還是有一定難度的。這里以vue為基礎(chǔ),講一種實(shí)現(xiàn)彈幕滾動(dòng)的方法,不考慮重疊,彈幕過(guò)長(zhǎng)或其他問(wèn)題。
???????一個(gè)彈幕即為一個(gè)組件,所以要實(shí)現(xiàn)設(shè)計(jì)此子組件,即彈幕組件,這里屬性要包含該彈幕的位置(隨機(jī)、定端、底端),大小,顏色,內(nèi)容等等,由父組件循環(huán)渲染并賦值。
???????生成一個(gè)彈幕并不難,難就難在如何讓其移動(dòng),第一個(gè)想到的點(diǎn)就是設(shè)其position為relative或是absolute,通過(guò)修改left或right使其移動(dòng)。那么選擇relative還是absolute呢?他們的效果是否一樣呢?

1.彈幕的position為relative還是absolute

???????這里我推薦使用absolute,而且效果是不一樣的,如果使用relative,將會(huì)導(dǎo)致新div(彈幕)每次生成時(shí)的位置會(huì)受前面的div或組件影響到,這時(shí)修改位置就會(huì)不準(zhǔn)確,即使使其float,也會(huì)受前面彈幕堆疊的影響而不能準(zhǔn)確使其生成在固定的某一位置。
???????如果使用absolute,就可以保證每次生成的橫向位置是固定的,不會(huì)收到前面的div/組件的影響,進(jìn)而準(zhǔn)確的調(diào)整其left/right(但是重疊無(wú)法避免)。
???????接下來(lái)是第二個(gè)問(wèn)題:

2.彈幕的left/right通過(guò)js修改與通過(guò)css的transition過(guò)渡比較

???????要實(shí)現(xiàn)彈幕勻速平穩(wěn)的移動(dòng),首先當(dāng)然可以使用js來(lái)操作,通過(guò)設(shè)置定時(shí)器,不停地一點(diǎn)一點(diǎn)地修改彈幕地位置來(lái)實(shí)現(xiàn)肉眼上彈幕地勻速滾動(dòng),但我想說(shuō)這樣太麻煩了。
???????你需要考慮不同div大小導(dǎo)致地彈幕移動(dòng)速度地變化,這時(shí)你需要通過(guò)計(jì)算來(lái)獲取每次彈幕移動(dòng)地增量(即速度),你還要調(diào)試定時(shí)器地時(shí)間,你還要遍歷每一條彈幕一次進(jìn)行修改,十分繁瑣。
???????但是,如果你使用transition地過(guò)度來(lái)實(shí)現(xiàn),就十分地簡(jiǎn)單:

transition-property: left;
transition-duration: 6s;
transition-timing-function: linear;

???????這里對(duì)隨機(jī)滾動(dòng)地彈幕做過(guò)度處理,注意這里特指隨機(jī),因?yàn)楣潭ǘǘ撕凸潭ǖ锥耸撬查g出現(xiàn)而且沒(méi)有變化,不應(yīng)該有次樣式,所以因該通過(guò)class綁定來(lái)解決。
???????當(dāng)你使用了transition之后你只用關(guān)心幾個(gè)數(shù)值即可:

  • 彈幕的初始位置(left & top)
  • 彈幕的結(jié)束位置(left & top)
  • 彈幕的過(guò)度屬性 transition-property(一般以x軸做勻速運(yùn)動(dòng),就只有l(wèi)eft,當(dāng)然b站有斜的彈幕)
  • 彈幕的運(yùn)動(dòng)時(shí)間 transition-duration (當(dāng)使用transition時(shí)就不考慮速度了,只用考慮運(yùn)動(dòng)時(shí)間即可)
  • 彈幕運(yùn)動(dòng)的方式 transition-timing-function(一般為linear,即線性)

???????這里最強(qiáng)大的樣式即為transition-duration,它使你不用再去關(guān)注彈幕具體的移動(dòng)速度,在不同寬度的div下重新計(jì)算彈幕的速度,以免彈幕消失過(guò)快或者過(guò)早。而transition-duration會(huì)智能的調(diào)節(jié)移動(dòng)的速度,保證這個(gè)彈幕一定會(huì)在此div移動(dòng)固定的時(shí)間。當(dāng)div長(zhǎng)時(shí),移動(dòng)加快,當(dāng)短時(shí),移動(dòng)變慢,但時(shí)間是一致的,而且你也不用再去寫(xiě)新的js方法,十分的方便。
???????這里,我將我寫(xiě)的彈幕的核心移動(dòng)算法列出來(lái):

created() {
            // console.log(this.position)
            var _self = this;
            var danWidth;
            var danHeight;
            //彈幕生成速度需時(shí)間,以免ref獲取為undefined
            window.setTimeout(function() {
                danWidth = _self.$refs.dan.offsetWidth    //彈幕的寬
                danHeight = _self.$refs.dan.offsetHeight  //彈幕的高
                if (_self.position == 0) {  //0指彈幕位置隨機(jī)
                    _self.top = Math.ceil(Math.random() * (_self.top - 60 - danHeight)); //縱向隨機(jī)高度
                    _self.left = - danWidth  //目標(biāo)移動(dòng)位置
                } else if (_self.position == 1) {    //1為固定頂部居中
                    _self.top = 5
                    _self.left = (_self.width-danWidth)/2     //居中
                } else {  //2為固定底部居中
                    _self.top = _self.top - 60 - danHeight
                    _self.left = (_self.width-danWidth)/2     //居中
                }
            }, 100);
            //6秒移動(dòng),7秒后刪除
            window.setTimeout(function() {
                _self.$emit('deletedan', _self.id)  //調(diào)用父級(jí)方法去除該彈幕
            }, 7000);
        }

???????其中_self.top即為彈幕上偏移量,_self.left為左偏移量,_self.width為父div(彈幕框)的寬,_self.height為父div的高。
???????首先要熟悉style綁定,這里首先把彈幕的left調(diào)整為父div(彈幕框)的寬度,正好右側(cè)溢出。此時(shí)延遲了100ms后將其移動(dòng)到left=負(fù)的彈幕的寬度,正好到左側(cè)溢出,這里之所以做延遲處理首先是保證先后順序要正確,其次彈幕(該組件)生成需要時(shí)間,要獲取彈幕寬高不能立馬通過(guò)ref屬性獲取,否則為undefined。
???????通過(guò)position(0,1,2)進(jìn)行相應(yīng)移動(dòng)處理后,再調(diào)用延遲進(jìn)行刪除處理,這個(gè)就比較簡(jiǎn)單了,直接在父級(jí)寫(xiě)一個(gè)方法,將彈幕id傳過(guò)去,刪除即可:

deleteDanmu(ids) {
                this.danmus = this.danmus.filter(danmu => danmu.id != ids)
            },

???????而且并不會(huì)影響其他彈幕,但需要注意的是該刪除時(shí)間延遲最小為6100.(本例)
???????最后需要注意的是要給該組件的根div加上

white-space:nowrap;

???????這個(gè)可以避免彈幕內(nèi)容(數(shù)字、英文、中文等)在溢出時(shí)被折疊,而導(dǎo)致出現(xiàn)的異常問(wèn)題。
???????以上說(shuō)的即是使用transition實(shí)現(xiàn)彈幕滾動(dòng)效果時(shí)的核心問(wèn)題,當(dāng)這些實(shí)現(xiàn)后,剩下彈幕的美化就都是比較一般的問(wèn)題了,當(dāng)然本文并沒(méi)有指出彈幕重疊的解決方法。

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

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