亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > HTML > 正文

html5使用canvas實現彈幕功能示例

2024-08-26 00:19:59
字體:
來源:轉載
供稿:網友

最近在著手開發彈幕視頻網站,通過html5中的canvas實現了彈幕的功能。

那么閑言碎語不要講,先說思路后上代碼。

思路:從頁面布局上來說就是將一塊畫布覆蓋在了video標簽產生的視頻窗口之上,使用絕對定位就能實現了。最重要的就是js控制畫布上彈幕的顯示了,每一個彈幕都包裝成一個對象,對象包含的屬性有彈幕應該出現的時間,彈幕的顏色,彈幕是否是移動的以及彈幕的文本。彈幕對象擁有方法包含:設置彈幕的橫縱坐標,彈幕的移動函數。實現的原理,在監聽視頻開始播放的事件,在視頻開始播放時生成一個定時器,定時器每隔一個時間去遍歷循環彈幕對象數組并根據對象的屬性在畫布的適當位置上繪制出彈幕,計時器中除了繪制彈幕的代碼還有執行更新彈幕數組的代碼。

下圖是彈幕效果截屏

canvas,彈幕,canvas實現彈幕,html5

那么下面開始直接上代碼:

(function () {    window.onload=function () {        var video = document.getElementsByTagName("video")[0]        var cav = document.getElementsByTagName("canvas")[0]        //設置常量canvas的高度以及寬度        var cavWidth = 800         var cavHeight = 420        cav.width=cavWidth        cav.height=cavHeight         var ctx = cav.getContext("2d")        //存儲彈幕對象的數組        var capObjs = []        var lastItemTime        var capHeight = 20         var inputEle = document.getElementsByClassName("caption-input-text")[0]        var sendEle = document.getElementsByClassName("caption-sendButton")[0]        var colorUl = document.getElementsByClassName("colorItems")[0]        var ismoveInputEle = document.getElementsByClassName("caption-input-ismove")[0]        //彈幕顏色        var colors=["#fff","#FFCCCC","#CCFFCC","#CCCCFF","#FFFFCC","#CCFFFF"]        var selectedColorIndex = 0        var prevPlayTime = 0        //測試數據的數組        var testArrayCopy = []        var capobjId = 0        //彈幕在畫布中高度可能值組成的數組        var topObjs = [{blank:true , value : 20 ,index:0},                        {blank:true , value : 50 ,index:1},                        {blank:true , value : 80 ,index:2},                        {blank:true , value : 110 ,index:3},                        {blank:true , value : 140 ,index:4},                        {blank:true , value : 170 ,index:5},                        {blank:true , value : 200 ,index:6},                        {blank:true , value : 230 ,index:7},                        {blank:true , value : 260 ,index:8},                        {blank:true , value : 290 ,index:9},                        {blank:true , value : 320 ,index:10},                        {blank:true , value : 350 ,index:11},                        {blank:true , value : 380 ,index:12},                        {blank:true , value : 410 ,index:13}]//test data 測試數據var testArray = [{content:"ABCDEFGHIJKLMNOPQRSTUVWXYZ",time:"1",ismove:false,colorIndex:0},{content:"233333333333333",time:"2",ismove:true,colorIndex:0},{content:"干杯,哈哈哈~~~~~~",time:"2",ismove:true,colorIndex:5},{content:"干杯,哈哈哈~~~~~~",time:"2",ismove:true,colorIndex:4},{content:"干杯,哈哈哈~~~~~~",time:"2",ismove:true,colorIndex:4},{content:"干杯,哈哈哈~~~~~~",time:"2",ismove:true,colorIndex:0},{content:"干杯,哈哈哈~~~~~~",time:"2",ismove:true,colorIndex:0},{content:"233333333333333",time:"3",ismove:true,colorIndex:0},{content:"233333333333333",time:"3",ismove:true,colorIndex:0},{content:"233333333333333",time:"3",ismove:true,colorIndex:0},{content:"233333333333333",time:"3",ismove:true,colorIndex:0},{content:"233333333333333",time:"3",ismove:true,colorIndex:0},{content:"233333333333333",time:"3",ismove:true,colorIndex:0},{content:"233333333333333",time:"4",ismove:false,colorIndex:0},{content:"233333333333333",time:"5",ismove:true,colorIndex:4},{content:"233333333333333",time:"6",ismove:true,colorIndex:2},{content:"233333333333333",time:"7",ismove:true,colorIndex:2},{content:"233333333333333",time:"7",ismove:true,colorIndex:2},{content:"233333333333333",time:"7",ismove:true,colorIndex:2},{content:"233333333333333",time:"7",ismove:true,colorIndex:2},{content:"233333333333333",time:"7",ismove:true,colorIndex:2},{content:"233333333333333",time:"7",ismove:true,colorIndex:2},{content:"233333333333333",time:"8",ismove:true,colorIndex:0},{content:"233333333333333",time:"9",ismove:true,colorIndex:0},{content:"233333333333333",time:"10",ismove:true,colorIndex:0},{content:"老師說的非常好,我要好好學習了》》》》",time:"12",ismove:true,colorIndex:0},{content:"老師說的非常好,我要好好學習了》》》》",time:"13",ismove:true,colorIndex:0},{content:"老師說的非常好,我要好好學習了》》》》",time:"14",ismove:true,colorIndex:2},{content:"老師說的非常好,我要好好學習了》》》》",time:"15",ismove:false,colorIndex:0},{content:"老師說的非常好,我要好好學習了》》》》",time:"16",ismove:true,colorIndex:2},{content:"老師說的非常好,我要好好學習了》》》》",time:"17",ismove:true,colorIndex:3},{content:"老師說的非常好,我要好好學習了》》》》",time:"18",ismove:true,colorIndex:2},{content:"老師說的非常好,我要好好學習了》》》》",time:"19",ismove:true,colorIndex:0},{content:"老師說的非常好,我要好好學習了》》》》",time:"20",ismove:true,colorIndex:3},{content:"老師說的非常好,我要好好學習了》》》》",time:"21",ismove:true,colorIndex:0},{content:"老師說的非常好,我要好好學習了》》》》",time:"22",ismove:true,colorIndex:0},{content:"老鐵們,小禮物走一波了,小汽車小火箭刷起來吧=========",time:"23",ismove:true,colorIndex:0},{content:"老鐵們,小禮物走一波了,小汽車小火箭刷起來吧=========",time:"24",ismove:true,colorIndex:0},{content:"老鐵們,小禮物走一波了,小汽車小火箭刷起來吧=========",time:"25",ismove:true,colorIndex:3},{content:"老鐵們,小禮物走一波了,小汽車小火箭刷起來吧=========",time:"26",ismove:true,colorIndex:0},{content:"老鐵們,小禮物走一波了,小汽車小火箭刷起來吧=========",time:"27",ismove:true,colorIndex:5},{content:"老鐵們,小禮物走一波了,小汽車小火箭刷起來吧=========",time:"28",ismove:false,colorIndex:5},{content:"老鐵們,小禮物走一波了,小汽車小火箭刷起來吧=========",time:"29",ismove:true,colorIndex:5},{content:"老鐵們,小禮物走一波了,小汽車小火箭刷起來吧=========",time:"30",ismove:true,colorIndex:5},{content:"馬上就下課了,瓦羅藍大陸走起了~~~",time:"31",ismove:true,colorIndex:5},{content:"馬上就下課了,瓦羅藍大陸走起了~~~",time:"32",ismove:true,colorIndex:2},{content:"馬上就下課了,瓦羅藍大陸走起了~~~",time:"33",ismove:true,colorIndex:2},{content:"馬上就下課了,瓦羅藍大陸走起了~~~",time:"33",ismove:true,colorIndex:5},{content:"馬上就下課了,瓦羅藍大陸走起了~~~",time:"34",ismove:true,colorIndex:5},{content:"馬上就下課了,瓦羅藍大陸走起了~~~",time:"35",ismove:true,colorIndex:5},{content:"馬上就下課了,瓦羅藍大陸走起了~~~",time:"36",ismove:true,colorIndex:2},{content:"馬上就下課了,瓦羅藍大陸走起了~~~",time:"37",ismove:true,colorIndex:2}]        //將測試數據備份        copyArray(testArray , testArrayCopy)        /*彈幕對象的構造函數,參數分別是:1.ismove:彈幕是否是移動的彈幕,2.spe:彈幕的移動速度,3.col:彈幕的顏色,4.text:彈幕的文本*/        /*原型鏈方法 setTopValue設置縱坐標,setLeftValue設置橫坐標,moving完成坐標的改變,setId完成id值的設置*/        function Caption( ismove , spe , col , text ) {            this.isMove = ismove            this.speed = spe            this.color = col || "#ff0"            this.content = text            this.latestTime = 0             this.width = text.length * 20             this.id = 0            this.topIndex = 0            this.occupyPos = true             this.top = 300            this.left = 0            this.setLeftValue()            this.setTopValue()        }        Caption.prototype.setTopValue = function  () {            for(var i = 0 ,len = topObjs.length ; i < len ; i++){                if (topObjs[i].blank) {                    this.top = topObjs[i].value                    this.topIndex = i                    topObjs[i].blank = false                     break                }            }        }        Caption.prototype.setLeftValue = function  () {            if (this.isMove) {                this.left = cavWidth            }            else {                var contentLength = this.content.length                var nowItemLeft = 420 - contentLength * 9                this.left = nowItemLeft            }        }        Caption.prototype.moving = function () {            if (this.isMove) {                this.left-=this.speed                if ( this.left + this.width < cavWidth && this.occupyPos) {                    this.occupyPos = false                     topObjs[this.topIndex].blank = true                 }            }             else{                this.latestTime += 1                if (this.latestTime > 450) {                    topObjs[this.topIndex].blank = true                 }            }        }        Caption.prototype.setId = function  () {            this.id = capobjId            capobjId++        }        var cap1 = new Caption(  false , 1 , 0 , "小禮物走一波,雙擊6666。。。。")        capObjs.push(cap1)        cap1.setId()                //循環遍歷數組,根據對象的屬性繪制在畫布上        function drawAllText () {            ctx.clearRect( 0 , 0 , cavWidth , cavHeight)            ctx.beginPath()            for(var i=0 , len = capObjs . length ; i < len ; i++ ){                ctx.fillStyle = capObjs[i].color                ctx.font = "bold 20px Courier New"                ctx.fillText( capObjs[i].content , capObjs[i].left , capObjs[i].top )                ctx.closePath()                capObjs[i].moving()                // if (capObjs[i].left < - cavWidth ) {                    // capObjs.splice (i ,1)                    // if excute this statement , will has fault because some item in array is null                    // solution is : write a new function to refresh the array                   // }            }        }                //更新數組,當對象已經超出范圍的時候從數組刪除這個對象        function refreshObjs(objs) {            for (var i = objs.length - 1; i >= 0; i--) {                if (objs[i].left < - cavWidth || objs[i].latestTime > 450 ) {                    objs.splice(i , 1)                }            }        }                //更新保存彈幕對象的數組        function updateArray () {            var now = parseInt( video.currentTime )            for (var i = testArray.length - 1; i >= 0; i--) {                var nowItemTime = parseInt(testArray[i].time)                 if ( nowItemTime == now ) {                    //首次寫的控制高度的方式,空間利用不充分,后來改為setTopValue中的方式                    // var nowItemLeft = getLeftValue(testArray[i])                    // var diffTime = Math.abs(nowItemTime - lastItemTime)                    // if (diffTime < 6) {                     //     capHeight += 30                    //     capHeight = capHeight > 400 ? 20 : capHeight                    // }                        var temcolor = colors[testArray[i].colorIndex]                    var temcap = new Caption (  testArray[i].ismove , 1 , temcolor , testArray[i].content  )                    capObjs.push(temcap)                    capObjs[capObjs.length - 1].setId()                    temcap = null                    testArray.splice(i,1)                }            }        }                //當用戶點擊send發送彈幕的回調函數        function sendCaption (argument) {            var inputEleTxt = inputEle.value            var now = parseInt( video.currentTime )            var inputIsmoveValue = ismoveInputEle.checked            var temObj = {content:inputEleTxt,time:now,ismove:inputIsmoveValue,colorIndex:selectedColorIndex}            testArray.push(temObj)            inputEle.value = ""        }        // function getLeftValue (obj) {        //     if (obj.ismove) {        //         return 0        //     }        //     else {        //         var contentLength = obj.content.length        //         var nowItemLeft = 420 - contentLength * 9        //         return nowItemLeft        //     }        // }                //重新啟動canvas,用在人為導致進度條時間的改變        function reinitCav (argument) {            // testArray = testArrayCopy            copyArray(testArrayCopy , testArray)            capObjs = []            capHeight = 0            clearInterval(canvasTimer)            canvasTimer = null            initCanvas()        }        var canvasTimer = null                 //初始化canvas,用在開始播放時         function initCanvas () {             if (canvasTimer == null ) {                canvasTimer = setInterval(function (argument) {                    drawAllText()                    updateArray()                    refreshObjs(capObjs)                },10)             }                    }//end function initCanvas                //復制數組        function copyArray (arr1 , arr2) {            for (var i =0 , len=arr1.length ; i < len ; i++) {                    arr2[i] = arr1[i]                }            }        //color select event 用戶發送彈幕的顏色控制代碼        colorUl.addEventListener("click", function( e ){            var prevSelectItemId = ""            switch (selectedColorIndex) {                case 0:                    prevSelectItemId = "colorItemFrist"                    break;                case 1:                    prevSelectItemId = "colorItemSecond"                    break;                case 2:                    prevSelectItemId = "colorItemThrid"                    break;                case 3:                    prevSelectItemId = "colorItemFourth"                    break;                case 4:                    prevSelectItemId = "colorItemFifth"                     break;                case 5:                    prevSelectItemId = "colorItemSixth"                    break;                default:                    // statements_def                    break;            }            var prevSelectItem = document.getElementById(prevSelectItemId)            prevSelectItem.className = ""            var eventTarget = e.target            eventTarget.className = "selectedColor"            var eveTarId = eventTarget.id.substring(9)            switch (eveTarId) {                case "Frist":                    selectedColorIndex = 0                    break;                case "Second":                    selectedColorIndex = 1                    break;                case "Thrid":                    selectedColorIndex = 2                    break;                case "Fourth":                    selectedColorIndex = 3                    break;                case "Fifth":                    selectedColorIndex = 4                    break;                case "Sixth":                    selectedColorIndex = 5                    break;                default:                    // statements_def                    break;            }        }, false)        video.addEventListener("playing" , function () {            initCanvas()        })                //進度條改變執行代碼        video.addEventListener("timeupdate", function  () {            var nowPlayTime = video.currentTime            var diffTime = Math.abs(nowPlayTime - prevPlayTime)            prevPlayTime = nowPlayTime            if (diffTime > 1) {                reinitCav()            }        }, false)                //視頻暫停執行代碼        video.addEventListener("pause" , function () {            clearInterval(canvasTimer)            canvasTimer = null         })                //點擊send的監聽事件        sendEle.addEventListener("click" , sendCaption)                //input的回車監聽事件        inputEle.addEventListener("keydown", function(e) {            var keynum = 0            keynum = window.event ? e.keyCode : e.which            if (keynum == 13) {                sendCaption()            }        })        var aaaa = function() {            alert(1)        }        aaaa()        // function b(aaaa){        //     return aaaa()        // }        // b()        }//end})()

希望能夠對想要制作彈幕的同學有所幫助,還可以去github下載完整的項目代碼:gitbub項目地址

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到HTML教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
一级做a爰片久久毛片美女图片| 人人澡人人澡人人看欧美| 久久韩国免费视频| 国产精品精品视频| 欧美黑人极品猛少妇色xxxxx| 亚洲网在线观看| 日韩综合视频在线观看| 美女精品久久久| 国产精品一区二区久久| 亚洲综合中文字幕在线| 日韩精品极品毛片系列视频| 精品性高朝久久久久久久| 日本一欧美一欧美一亚洲视频| 国产专区欧美专区| 久久成人国产精品| 亚洲视频网站在线观看| 国产精品久久久久福利| 久久国产精彩视频| 国产精品久久久久久久久久尿| 亚洲最大av网站| 亚洲天堂男人天堂| 国产一区二区精品丝袜| 91av免费观看91av精品在线| 亚洲 日韩 国产第一| 日韩精品一二三四区| 中文字幕在线看视频国产欧美在线看完整| 国产午夜精品美女视频明星a级| 精品亚洲国产视频| 97在线精品视频| 神马久久久久久| 91影院在线免费观看视频| 欧美激情欧美激情在线五月| www国产亚洲精品久久网站| 精品一区电影国产| 在线观看欧美视频| 亚洲a∨日韩av高清在线观看| 国产成人啪精品视频免费网| 欧美洲成人男女午夜视频| 欧美高清视频一区二区| 欧美在线免费观看| 97精品国产91久久久久久| 欧美色视频日本版| 色哟哟亚洲精品一区二区| 亚洲综合大片69999| 韩国v欧美v日本v亚洲| 国产精选久久久久久| 精品国产户外野外| 欧美精品久久久久久久免费观看| 色综合久久天天综线观看| 日韩免费视频在线观看| 一区三区二区视频| 国产成人精品综合久久久| 亚洲精品永久免费| 欧美亚洲一级片| 欧美精品久久久久久久免费观看| 国产精品高潮呻吟视频| 最近2019中文字幕大全第二页| 国产91热爆ts人妖在线| 欧美裸体xxxx| 亚洲一区二区在线| 国模精品视频一区二区三区| 亚洲一区二区久久久久久| 欧美日韩国产在线看| 色哟哟入口国产精品| 9.1国产丝袜在线观看| 九色精品免费永久在线| 亚洲综合在线播放| 欧美精品国产精品日韩精品| 国产精品久久久久久久久久免费| 欧美一级视频一区二区| 国产精品日韩av| 尤物yw午夜国产精品视频明星| 欧美亚洲国产另类| 久久手机精品视频| 亚洲黄色片网站| 欧美片一区二区三区| 欧美裸体男粗大视频在线观看| 国产成人精品视| 国产一区二区成人| 欧美大人香蕉在线| 国产综合在线视频| 91黑丝高跟在线| 中文字幕欧美在线| 欧美大成色www永久网站婷| 国产精自产拍久久久久久蜜| 欧美日韩国产区| 国产精品久久不能| 亚洲一区亚洲二区亚洲三区| 久热99视频在线观看| 有码中文亚洲精品| 日韩电影免费在线观看中文字幕| 欧美壮男野外gaytube| 日本国产欧美一区二区三区| 精品国内亚洲在观看18黄| 日韩在线视频观看正片免费网站| 伊人精品在线观看| 亚洲国产日韩欧美在线99| 久久久久久久影视| 亚洲专区在线视频| 亚洲欧美第一页| 欧美www在线| 国内精品久久影院| 亚洲男人天堂2024| 欧美日韩在线免费观看| 69视频在线播放| 亚洲国产精品va| 亚洲精品99999| 欧美专区在线播放| 精品久久久久人成| 日韩精品中文字幕视频在线| 日本成人免费在线| 欧美精品日韩www.p站| 亚洲嫩模很污视频| 中文字幕欧美精品日韩中文字幕| 国产国语videosex另类| 日韩欧美大尺度| 亚洲高清一二三区| 亚洲国产成人一区| 亚洲天堂一区二区三区| 亚洲最大的成人网| 欧美裸体xxxx极品少妇软件| 日韩中文字幕亚洲| 美女久久久久久久久久久| 亚洲欧洲在线播放| 国产精品色婷婷视频| 国产美女直播视频一区| 亚洲视频一区二区| 亚洲国产成人爱av在线播放| 亚洲视频视频在线| 精品久久久久久久久久久久久久| 日韩欧美精品网址| 亚洲欧美日韩一区在线| 国产精品丝袜白浆摸在线| 综合久久五月天| 91在线国产电影| 欧美黑人xxxx| 欧美激情一二区| 欧美日韩在线看| 亚洲色图国产精品| 亚洲精品98久久久久久中文字幕| 超碰日本道色综合久久综合| 亚洲精品永久免费| 欧美性猛交xxxx黑人猛交| 色久欧美在线视频观看| 久久久久久久久亚洲| 欧美日韩不卡合集视频| 欧美电影在线观看高清| 国产精品一区久久| 国产精品久久久久免费a∨大胸| 久久精品2019中文字幕| 日韩成人激情视频| 久久精品国产一区二区电影| 91免费看片在线| 中文字幕不卡在线视频极品| 国产精品99免视看9| 成人免费直播live| 欧美激情在线播放| 九九九久久久久久| 欧美日韩精品国产| 欧美贵妇videos办公室| 欧美成人在线影院| 国产成人在线亚洲欧美| 萌白酱国产一区二区| 96pao国产成视频永久免费|