Canvas彈幕實(shí)現(xiàn)


anvas原生實(shí)現(xiàn)直播視頻彈幕效果钠糊。

原文鏈接

上一篇中用動態(tài)創(chuàng)建DOM元素實(shí)現(xiàn)彈幕效果,好處是可以在DOM元素上添加事件壹哺,但問題是當(dāng)大量彈幕出現(xiàn)會造成頁面卡頓抄伍,于是嘗試用canvas繪制彈幕效果。

canvas知識

繪制文字

let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
ctx.font = '20px Microsoft YaHei';          //字體管宵、大小
ctx.fillStyle = '#000000';                  //字體顏色
ctx.fillText('canvas 繪制文字', 100, 100);   //文本截珍,字體x,y坐標(biāo)

文本寬度

ctx.measureText('文本寬度').width

清除繪制內(nèi)容

ctx.clearRect(0, 0, width, height);    

實(shí)現(xiàn)步驟

1、創(chuàng)建canvas元素利用絕對定位覆蓋在視頻上
2箩朴、創(chuàng)建Barrage類岗喉,添加的彈幕緩存到彈幕列表中,并記錄相應(yīng)彈幕信息
3炸庞、繪制彈幕文本钱床,用文本偏移量控制移動速度
4、計算當(dāng)文本超出畫布時移出彈幕列表

代碼

//html
<div style="position:relative;width:500px;height:400px;text-align:center;">
    <video controls="controls" autoplay="autoplay" style="width:100%;height:100%;">
        <source src="http://www.w3school.com.cn/i/movie.ogg" type="video/ogg" />
        <source src="http://www.w3school.com.cn/i/movie.mp4" type="video/mp4" /> 
        Your browser does not support the video tag.
    </video>

    <canvas id="canvas" width="500" height="400" style="position:absolute;top:0;left:0;">
        您的瀏覽器不支持canvas標(biāo)簽埠居。
    </canvas>
</div>

//js
(function () {

    class Barrage {
        constructor(canvas) {
            this.canvas = document.getElementById(canvas);
            let rect = this.canvas.getBoundingClientRect();
            this.w = rect.right - rect.left;
            this.h = rect.bottom - rect.top;
            this.ctx = this.canvas.getContext('2d');
            this.ctx.font = '20px Microsoft YaHei';
            this.barrageList = [];
        }

        //添加彈幕列表
        shoot(value) {
            let top = this.getTop();
            let color = this.getColor();
            let offset = this.getOffset();
            let width = Math.ceil(this.ctx.measureText(value).width);

            let barrage = {
                value: value,
                top: top,
                left: this.w,
                color: color,
                offset: offset,
                width: width
            }
            this.barrageList.push(barrage);
        }

        //開始繪制
        draw() {
            if (this.barrageList.length) {
                this.ctx.clearRect(0, 0, this.w, this.h);
                for (let i = 0; i < this.barrageList.length; i++) {
                    let b = this.barrageList[i];
                    if (b.left + b.width <= 0) {
                        this.barrageList.splice(i, 1);
                        i--;
                        continue;
                    }
                    b.left -= b.offset;
                    this.drawText(b);
                }
            }
            requestAnimationFrame(this.draw.bind(this));
        }

        //繪制文字
        drawText(barrage) {
            this.ctx.fillStyle = barrage.color;
            this.ctx.fillText(barrage.value, barrage.left, barrage.top);
        }

        //獲取隨機(jī)顏色
        getColor() {
            return '#' + Math.floor(Math.random() * 0xffffff).toString(16);
        }

        //獲取隨機(jī)top
        getTop() {
            //canvas繪制文字x,y坐標(biāo)是按文字左下角計算诞丽,預(yù)留30px
            return Math.floor(Math.random() * (this.h - 30)) + 30;
        }

        //獲取偏移量
        getOffset() {
            return +(Math.random() * 4).toFixed(1) + 1;
        }

    }

    let barrage = new Barrage('canvas');
    barrage.draw();

    const textList = ['彈幕', '666', '233333333', 
        'javascript', 'html', 'css', '前端框架', 'Vue', 'React',
        'Angular','測試彈幕效果'
    ];

    textList.forEach((t) => {
        barrage.shoot(t);
    })

})();

效果

效果

總結(jié)

canvas可以實(shí)現(xiàn)很多動畫效果,尤其是當(dāng)我們需要動態(tài)創(chuàng)建大量元素時拐格,使用canvas可以優(yōu)化動畫顯示效果,改善用戶體驗(yàn)刑赶,提升性能捏浊。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市撞叨,隨后出現(xiàn)的幾起案子金踪,更是在濱河造成了極大的恐慌,老刑警劉巖牵敷,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胡岔,死亡現(xiàn)場離奇詭異,居然都是意外死亡枷餐,警方通過查閱死者的電腦和手機(jī)靶瘸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來毛肋,“玉大人怨咪,你說我怎么就攤上這事∪蟪祝” “怎么了诗眨?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長孕讳。 經(jīng)常有香客問我匠楚,道長巍膘,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任芋簿,我火速辦了婚禮峡懈,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘益咬。我一直安慰自己顷牌,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布侦啸。 她就那樣靜靜地躺著突颊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪冗锁。 梳的紋絲不亂的頭發(fā)上齐唆,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天,我揣著相機(jī)與錄音冻河,去河邊找鬼箍邮。 笑死,一個胖子當(dāng)著我的面吹牛叨叙,可吹牛的內(nèi)容都是我干的锭弊。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼擂错,長吁一口氣:“原來是場噩夢啊……” “哼味滞!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起钮呀,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤剑鞍,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后爽醋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚁署,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年蚂四,在試婚紗的時候發(fā)現(xiàn)自己被綠了光戈。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡遂赠,死狀恐怖田度,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情解愤,我是刑警寧澤镇饺,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站送讲,受9級特大地震影響奸笤,放射性物質(zhì)發(fā)生泄漏惋啃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一监右、第九天 我趴在偏房一處隱蔽的房頂上張望边灭。 院中可真熱鬧,春花似錦健盒、人聲如沸绒瘦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽惰帽。三九已至,卻和暖如春父虑,著一層夾襖步出監(jiān)牢的瞬間该酗,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工士嚎, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留呜魄,地道東北人。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓莱衩,卻偏偏與公主長得像爵嗅,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子笨蚁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容