說起彈幕看過視頻的都不會陌生,那滿屏充滿著飄逸評論的效果,讓人如癡如醉,無法自拔
最近也是因為在學習關于 canvas 的知識,所以今天就想和大家分享一個關于彈幕的故事
那么究竟彈幕是怎樣煉成的呢? 我們且往下看(look)
看什么?看效果
效果圖已經呈現給各位了,那么是不是有點小激動呢?是的,感慨萬分,思緒寧亂,無語凝噎
無論以后我們的工作中是否會遇到這樣的需求,也請給自己一個增加技能的機會吧!!
本次彈幕的效果,項目結構如下圖所示
項目整體已經給出,那么我們就擼起袖子加油干吧。
讓彈幕飛
上面我們提到了 canvas 的事情,所以呢,這就是制作彈幕了。我們利用 canvas 繪圖來實現彈幕的功能
首先,我們先給出html的結構
// index.html文件// 引入index.js文件用來實現彈幕功能聽媽媽的話 - 周杰倫
結構相對來說沒什么高級的內容,主要就是寫上了 canvas 標簽還有 video 標簽,他們才是視頻網站彈幕的絕佳拍檔
那么不再賣關子了,趕緊進行主要活動吧
模擬數據
// index.js文件 let data = [ {value: "周杰倫的聽媽媽的話,讓我反復循環再循環", time: 5, color: "red", speed: 1, fontSize: 22}, {value: "想快快長大,才能保護她", time: 10, color: "#00a1f5", speed: 1, fontSize: 30}, {value: "聽媽媽的話吧,晚點再戀愛吧!愛呢?", time: 15}, ];
數據里代表了什么:
value:代表彈幕的內容 (必填)
time:代表彈幕展現的時間 (必填)
color:代表彈幕文字的顏色
speed:代表彈幕飄過的速度
fontSize:代表彈幕文字的大小
opacity:代表彈幕文字的透明度
除了彈幕的內容和展現的時間外,其他都是可選的,模擬的數據里沒有這些參數也沒關系的
獲取 dom 元素
// index.js文件 // 模擬數據 ...省略 // 獲取到所有需要的dom元素 let doc = document; let canvas = doc.getElementById("canvas"); let video = doc.getElementById("video"); let $txt = doc.getElementById("text"); let $btn = doc.getElementById("btn"); let $color = doc.getElementById("color"); let $range = doc.getElementById("range");
Canvas渲染彈幕
下面我們將用面向對象的方式來實現canvas繪制彈幕的功能,之所以選擇用這種方式主要是方便復用和后續添加方法;
下面我們先來創建一個CanvasBarrage類,主要用做canvas來渲染整個彈幕;
在實現之前,我們先來調用一下,看看是如何創建實例的。
// index.js文件 // 模擬數據 ...省略 // 獲取到所有需要的dom元素 ...省略 // 創建CanvasBarrage類 class CanvasBarrage { // todo } // 創建CanvasBarrage實例 let canvasBarrage = new CanvasBarrage(canvas, video, { data });
實現 CanvasBarrage
我們在“得到所有的彈幕消息”那里,通過數組的 map 方法返回的還是個數組,不過返回的內容是一個 Barrage類,這是為什么呢?
還記得之前說過么,用類的好處就是方便擴展,后續再添加方法的話可以直接在該類中添加即可。
所以我們也不推崇直接map方法里直接返回一個{}這種形式
// 不推薦 this.barrages = this.data.map(item => { item });
說到這里我們還要先寫一下Barrage這個類,不然接下來的console.log(this)會因為找不到Barrage類而報錯
// index.js文件 ++++++++++++++++++++++ // 創建Barrage類,用來實例化每一個彈幕元素 class Barrage { constructor(obj, ctx) { // todo } } ++++++++++++++++++++++ class CanvasBarrage { ...省略}
Now,通過上面代碼中的console.log(this),我們可以看到,所有掛載到this實例上的屬性和原型上的方法都呈現眼前了
render 一下
接著上面的 CanvasBarrage 類里 render 方法繼續寫,我們來把 todo 完成
todo都做了什么?
1、清除之前畫布所有的繪制,防止繪制重疊的影響
this.clear()
2、渲染真正的彈幕數據 (還未實現)
this.renderBarrage()
3、判斷是否繼續渲染彈幕
this.isPaused為false時表示為播放狀態
4、遞歸調用render
通過requestAnimationFrame來遞歸調用render
要比setInterval這樣的方式好很多
渲染整個彈幕 render 方法就完成了,那么要繼續寫了,應該是剛才未實現的 renderBarrage 方法了
But,在此之前,我們要先寫個別的,它就是Barrage類
因為還需要它來大顯身手一下呢,每一個彈幕的實例都由它來制造
創建 Barrage 類
彈幕制造者來了,下面我們就來實現一下這個Barrage類,看它都具備哪些屬性和方法,繼續todo吧
todo都做了什么?
1、從傳入的obj中取到必要的value和time
this.value = obj.value; // 內容 this.time = obj.time; // 時間
2、初始化彈幕
對每個彈幕所需的參數進行設置,如果obj上沒有,就取默認參數
計算每個彈幕的寬度
由于不能直接操縱canvas畫布里的元素,所以先創建一個p標簽
p標簽的寬度即為彈幕的寬 -> this.width = p.clientWidt
設置每個彈幕的x和y坐標 (起始位置)
橫向x坐標起始位置都是從右邊進入,即:畫布的寬度
this.x = this.context.canvas.width
縱向y坐標起始位置是不固定的,選在畫布之內的任意位置出現
this.y = this.context.canvas.height * Math.random()
處理彈幕超出畫布區域
canvas是按照字號基線來展示字體的,如果小于這個字號大小
this.y = this.fontSize
如果大于了畫布高度 - 字號大小
this.y = this.context.canvas.height - this.fontSize
3、渲染每個彈幕
繪制文本需要設置文本的字體字號、顏色和文本的內容與坐標
字體字號api
this.context.ctx.font = ${this.value}px Arial
顏色api
this.context.ctx.fillStyle = this.color
內容與坐標api
this.context.ctx.fillText(this.value, this.x, this.y)
以上三步就是整個Barrage類所做的事情了。Barrage這個類都已經敲完了,那么接下來開始真正的渲染步驟吧
renderBarrage才是主角
此時我們再添加一個觸發彈幕的事件,讓彈幕飛起來
大家一起寫到了這里,也是時候展示一下成果了,往下看
別急,讓彈幕再飛一會兒
渲染彈幕的功能,我們已經完成了,接下來讓我們馬不停蹄的寫下如何發彈幕吧。別猶豫,開擼!!!
發彈幕
發彈幕相對來說還是很簡單的,獲取到 value, time, color, fontSize 之后把他們當作對象傳給 CanvasBarrage 的 add方法進行添加就好了
下面我們再寫一下add方法,回到CanvasBarrage類里繼續寫
// index.js文件 class CanvasBarrage { constructor() { ...省略} render() { ...省略 } renderBarrage() { ...省略 } clear() { ...省略 } +++++++++++++++++++++++++++ add(obj) { // 實際上就是往barrages數組里再添加一項Barrage的實例而已 this.barrages.push(new Barrage(obj, this)); } +++++++++++++++++++++++++++ }
完成,漂亮,看看效果吧
寫到這里我們已經完成了視頻網站上的彈幕功能了,可喜可賀
下面我們再來完善一下視頻播放時對彈幕的播放處理吧
暫停和拖動
暫停就停止渲染彈幕
// index.js文件 ...省略 // 播放 video.addEventListener("play", () => { canvasBarrage.isPaused = false; canvasBarrage.render(); }); +++++++++++++++++++++++++++++++++++++++ // 暫停 video.addEventListener("pause", () => { // isPaused設為true表示暫停播放 canvasBarrage.isPaused = true; }); +++++++++++++++++++++++++++++++++++++++
回放時需要重新渲染該時刻的彈幕
// index.js文件 // 暫停 video.addEventListener("pause", () => { canvasBarrage.isPaused = true; }); +++++++++++++++++++++++++++++++++++++++ // 拖動進度條時觸發seeked事件 video.addEventListener("seeked", () => { // 調用CanvasBarrage類的replay方法進行回放,重新渲染彈幕 canvasBarrage.replay(); }); +++++++++++++++++++++++++++++++++++++++
讓我們再次回到CanvasBarrage這個類上
OK,寫到這里,所有關于彈幕功能的代碼就全部結束了!!
如果工作中讓你開發彈幕功能,你也可以在多敲幾遍以上代碼之后,得心應手的保證完成任務了。
敬請期待,下節更精彩
接下來我們再利用 WebSocket 和 redis 來進行一下較為實戰的功能吧。
作者:chenhongdong
來源:
https://juejin.im/post/5be54a...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/99996.html
摘要:歡迎訪問網易云社區,了解更多網易技術產品運營經驗。網易云易盾智能反垃圾服務,基于網易年專業的反垃圾經驗,以及積累的億級別的海量數據,為客戶提供極速智能的廣告過濾智能鑒黃暴恐識別涉政檢測云服務,助力打造互聯網純凈內容生態。文章來源網易云社區 歡迎訪問網易云社區,了解更多網易技術產品運營經驗。 人工審核對于A站和B站都是很重要的。 AcFun稿件審核通行標準(V1.1) 表明,要審核的東西...
摘要:要達到水平很高的程序員,第一要找能提供優質實踐機會的大廠,第二要在諸如高并發或機器學習的項目里多解決實際問題,第三還要不斷跳槽,不斷地找更優質的平臺和更優質的項目機會。 ...
摘要:提高有了入門的基礎,開始自學當時流行的三大框架和。業余的時間,經常在上閑逛,看一些博客或開源的代碼。 最近有一位小伙伴通過公眾號給我留言, 我參加工作沒多久,看著圈里的技術大牛,特別羨慕,也渴望成為技術大牛,想讓您分享一下從小白到大牛是怎樣練成的,我該如何提高自己 首先,謝謝這位小伙伴的一直關注。其次,我并不是大牛,只是早搬了幾年的磚而已,不過可以分享一下我的Java開發之路。 入門 ...
摘要:使用的的方法實現了文字滾動我們需要做一些準備工作例如我們為了讓彈幕可以變顏色我們寫了下面這個方法。判斷存儲彈幕信息的數據是否為空隨機抽取數組中的一個元素之后把它追加到這個中執行文字滾動的方法。 怎樣才能跑起來我寫的彈幕程序 資源下載 申請野狗后端云賬號注冊 創建應用:showImg(https://segmentfault.com/img/remote/146000000683932...
閱讀 1956·2021-11-22 15:29
閱讀 3252·2021-10-14 09:43
閱讀 1223·2021-10-08 10:22
閱讀 3342·2021-08-30 09:46
閱讀 1431·2019-08-30 15:55
閱讀 1923·2019-08-30 15:44
閱讀 849·2019-08-30 14:19
閱讀 1439·2019-08-30 13:13