一、canvas實(shí)現(xiàn)彈幕性能較好
從技術(shù)實(shí)現(xiàn)成本角度講,要實(shí)現(xiàn)彈幕效果,最簡(jiǎn)單的方法就是DOM+CSS3控制,如果我們的彈幕效果比較簡(jiǎn)單,使用CSS3動(dòng)畫(huà)實(shí)現(xiàn)也不失為一個(gè)好的方法。
但是如果我們的彈幕數(shù)據(jù)量比較大,就像下面這種:

使用DOM來(lái)實(shí)現(xiàn)很容易卡成了80年代的拖拉機(jī)——一頓一頓的。
很顯然,面對(duì)這種多元素的復(fù)雜動(dòng)畫(huà),使用canvas實(shí)現(xiàn)是更加合適的,動(dòng)畫(huà)會(huì)流暢很多。
本文就將展示兩個(gè)案例,使用canvas實(shí)現(xiàn)彈幕效果。其中一個(gè)效果是靜態(tài)的彈幕數(shù)據(jù)固定的無(wú)限循環(huán)的效果,適合在個(gè)人博客或者運(yùn)營(yíng)頁(yè)面,這種非視頻場(chǎng)景使用;另外一個(gè)效果是動(dòng)態(tài)的彈幕數(shù)據(jù)可變的和真實(shí)HTML5交互的彈幕效果,也就是真視頻彈幕效果。
兩個(gè)高保真demo的源代碼都是可以免費(fèi)使用的,使用MIT許可,也就是需要保留源代碼中的版權(quán)聲明。
好,下面我們一個(gè)人來(lái)看一下。
二、HTML5 canvas實(shí)現(xiàn)的靜態(tài)循環(huán)滾動(dòng)播放彈幕
先看效果,您可以狠狠地點(diǎn)擊這里:HTML5 canvas實(shí)現(xiàn)的靜態(tài)循環(huán)彈幕demo
效果截圖如下:

相關(guān)JS代碼直接查看頁(yè)面源代碼就可以看到了。
使用方法和API
語(yǔ)法如下:
canvasBarrage(canvas, data);
其中:
canvas
canvas表示我們的畫(huà)布元素,可以直接是DOM元素,也可以是畫(huà)布元素的選擇器。
data
data表示彈幕數(shù)據(jù),是一個(gè)數(shù)組。例如下面:
[{
value: '彈幕1',
color: 'blue',
range: [0, 0.5]
}, {
value: '彈幕2',
color: 'red',
range: [0.5, 1]
}]
可以看到數(shù)組中的每一個(gè)值表示一個(gè)彈幕的信息對(duì)象。其中value表示彈幕的文字內(nèi)容;color表示彈幕描邊的顏色(彈幕文字本身默認(rèn)是白色);range表示彈幕在畫(huà)布中的區(qū)域范圍,例如[0, 0.5]表示彈幕在畫(huà)布中的上半?yún)^(qū)域顯示,[0.5, 1]表示彈幕在畫(huà)布中的下半?yún)^(qū)域顯示。
然后就可以看到無(wú)限滾動(dòng)的彈幕效果了。
補(bǔ)充說(shuō)明:
此彈幕效果默認(rèn)文字大小是28px,并且文字加粗,如果這個(gè)效果不符合您的需求,需要在canvasBarrage()方法中修改源代碼。因?yàn)楸緛?lái)就是個(gè)簡(jiǎn)單靜態(tài)效果,因此沒(méi)有專門設(shè)計(jì)成API。
此彈幕效果默認(rèn)是白色文字加可變顏色描邊,同樣的,如果這個(gè)效果不符合您的需求,需要在canvasBarrage()方法中修改源代碼。
跟真實(shí)的彈幕效果有所不同,這里的彈幕出現(xiàn)的速度和時(shí)機(jī)不是基于特定時(shí)間,而是隨機(jī)產(chǎn)生。所以看到有些文字好像開(kāi)飛機(jī),而有些文字好像坐著拖拉機(jī)。因?yàn)槭撬罃?shù)據(jù),這樣設(shè)計(jì)會(huì)看上去更真實(shí)寫(xiě)。
三、canvas實(shí)現(xiàn)的和HTML5 video真實(shí)交互的彈幕
這個(gè)原型就有點(diǎn)厲害了,市面上估計(jì)很難找到這么負(fù)責(zé)任的原型頁(yè)面了。實(shí)現(xiàn)的動(dòng)機(jī)完全興趣使然,上面實(shí)現(xiàn)了個(gè)簡(jiǎn)單的,就想著要不實(shí)現(xiàn)一個(gè)真實(shí)的,萬(wàn)一以后用得到呢?
先來(lái)看效果,您可以狠狠的點(diǎn)擊這里:HTML5 canvas和mp4視頻真實(shí)交互彈幕demo
頁(yè)面效果截圖如下:

可以看到:
為了方便演示,我特意錄制了一個(gè)21秒的視頻;
可以實(shí)時(shí)更改彈幕的透明度字號(hào)大小位置等;
可以實(shí)時(shí)發(fā)送彈幕并顯示。
部分演示如下:
點(diǎn)擊播放按鈕:

1秒后,此時(shí)可以看到彈幕呈現(xiàn),2秒后有彈幕進(jìn)入:

設(shè)置位置居底顯示后:

也可以發(fā)送彈幕:


使用方法和API
語(yǔ)法如下:
new CanvasBarrage(canvas, video, options);
其中:
canvas
canvas表示我們的畫(huà)布元素,只能是DOM元素。
video
video表示我們播放的視頻元素,只能是DOM元素。
options
options為可選參數(shù),包括:
API名稱默認(rèn)值簡(jiǎn)單釋義
opacity100彈幕透明度。數(shù)值。0表示完全透明,100表示完全不透明。
fontSize24彈幕文字大小。數(shù)值。單位px。
speed2彈幕移動(dòng)速度。數(shù)值。單位px。如果設(shè)置為0,則表示彈幕不移動(dòng),直接視頻中間區(qū)域顯示。
range[0,1]彈幕顯示的垂直范圍。數(shù)組。支持兩個(gè)值。[0,1]表示彈幕整個(gè)隨機(jī)分布,[0,0.5]表示只在上半?yún)^(qū)域隨機(jī)分布,[0.5,1]表示只在下半?yún)^(qū)域隨機(jī)分布。
colorwhite文字顏色。字符串。顏色值,可以是關(guān)鍵字,也可以是16進(jìn)制顏色表示,例如#ff9000等。
data[]彈幕數(shù)據(jù)。數(shù)組。數(shù)組中的值只能是一個(gè)一個(gè)的彈幕數(shù)據(jù)對(duì)象,例如:
[{
value: '彈幕1',
time: 1
}, {
value: '彈幕2',
time: 2
}]
value和time是必須的,分布表示彈幕內(nèi)容,和彈幕在視頻播放到什么時(shí)候顯示(單位是秒)。其他可選參數(shù)包括options參數(shù)中除data以外的所有參數(shù),用來(lái)覆蓋全局設(shè)置,例如:
[{
value: '彈幕',
time: 1,
color: 'red'
}]
此時(shí)“彈幕”這個(gè)文字的顏色就不是默認(rèn)的白色,而是這里設(shè)置的紅色。
如何修改全局設(shè)置和添加彈幕?
當(dāng)我們使用new CanvasBarrage()構(gòu)造完我們的彈幕方法后,會(huì)返回一個(gè)彈幕對(duì)象,通過(guò)調(diào)用這個(gè)對(duì)象暴露的屬性和方法,就可以進(jìn)行全局的設(shè)置和添加彈幕等。例如:
var myBarrage = new CanvasBarrage(canvas, video, options);
如果我們想把彈幕透明度改成50%透明,可以:
myBarrage.opacity = 50;
就這么簡(jiǎn)單,于是新出現(xiàn)的彈幕都會(huì)以50%透明顯示,類似的,彈幕文字大小和顏色,彈幕顯示的區(qū)域范圍都可以通過(guò)這樣設(shè)置,例如:
myBarrage.fontSize = 20;
就是把彈幕文字顏色改成20px大小。
如果我們想動(dòng)態(tài)添加彈幕,可以使用暴露的add()方法,語(yǔ)法如下:
myBarrage.add(obj);
其中obj的參數(shù)類型和支持屬性和options-data數(shù)組中對(duì)象一模一樣。例如:
myBarrage.add({
value: 'new CanvasBarrage()',
color: '#ff0000',
time: 0
});
結(jié)果就是下面的效果:

myBarrage還暴露了一個(gè)名為reset()方法,可以清除屏幕上所有的彈幕,并重新根據(jù)視頻時(shí)間開(kāi)始運(yùn)動(dòng)與顯示。視頻點(diǎn)擊跳轉(zhuǎn)時(shí)候的彈幕處理就是調(diào)用的此方法。
補(bǔ)充說(shuō)明
以上演示的全部交互效果和語(yǔ)法說(shuō)明在demo頁(yè)面的源代碼中均有示意。
CanvasBarrage實(shí)例方法我已經(jīng)專門挪到一個(gè)名為canvasBarrage.js中。
最后,再次明確下,保留JS中的版權(quán)聲明,萬(wàn)一回頭這個(gè)JS升級(jí)了或者修復(fù)了某些問(wèn)題,你還可以溯源。
感謝LuLu UI對(duì)本demo提供的交互組件支持。
四、結(jié)束語(yǔ)
我特意看了下真實(shí)的視頻網(wǎng)站的HTML5 video視頻是如何處理彈幕效果的,例如騰訊視頻,發(fā)現(xiàn)是基于DOM實(shí)現(xiàn)的(JS+DOM):

然后B站也是基于DOM實(shí)現(xiàn)的,也就是一開(kāi)始我所說(shuō)的DOM+CSS3實(shí)現(xiàn):

然后我陷入了深深的沉思……
