h5怎么通過(guò)canvas來(lái)完成滾動(dòng)彈幕技巧
發(fā)表時(shí)間:2024-05-08 來(lái)源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]這次給大家?guī)?lái)h5怎樣通過(guò)canvas來(lái)實(shí)現(xiàn)滾動(dòng)彈幕功能,通過(guò)canvas實(shí)現(xiàn)滾動(dòng)彈幕功能的注意事項(xiàng)有哪些,下面就是實(shí)戰(zhàn)案例,一起來(lái)看一下。最近在著手開(kāi)發(fā)彈幕視頻網(wǎng)站,通過(guò)html5中的canvas實(shí)現(xiàn)了彈幕的功能。那么閑言碎語(yǔ)不要講,先說(shuō)思路后上代碼。思路:從頁(yè)面布局上來(lái)說(shuō)就是將一塊畫(huà)布覆蓋在了...
這次給大家?guī)?lái)h5怎樣通過(guò)canvas來(lái)實(shí)現(xiàn)滾動(dòng)彈幕功能,通過(guò)canvas實(shí)現(xiàn)滾動(dòng)彈幕功能的
注意事項(xiàng)有哪些,下面就是實(shí)戰(zhàn)案例,一起來(lái)看一下。
最近在著手開(kāi)發(fā)彈幕視頻網(wǎng)站,通過(guò)html5中的canvas實(shí)現(xiàn)了彈幕的功能。
那么閑言碎語(yǔ)不要講,先說(shuō)思路后上代碼。
思路:從頁(yè)面布局上來(lái)說(shuō)就是將一塊畫(huà)布覆蓋在了video標(biāo)簽產(chǎn)生的視頻窗口之上,使用絕對(duì)定位就能實(shí)現(xiàn)了。最重要的就是js控制畫(huà)布上彈幕的顯示了,每一個(gè)彈幕都包裝成一個(gè)對(duì)象,對(duì)象包含的屬性有彈幕應(yīng)該出現(xiàn)的時(shí)間,彈幕的顏色,彈幕是否是移動(dòng)的以及彈幕的文本。彈幕對(duì)象擁有方法包含:設(shè)置彈幕的橫縱坐標(biāo),彈幕的移動(dòng)函數(shù)。實(shí)現(xiàn)的原理,在監(jiān)聽(tīng)視頻開(kāi)始播放的事件,在視頻開(kāi)始播放時(shí)生成一個(gè)定時(shí)器,定時(shí)器每隔一個(gè)時(shí)間去遍歷循環(huán)彈幕對(duì)象數(shù)組并根據(jù)對(duì)象的屬性在畫(huà)布的適當(dāng)位置上繪制出彈幕,計(jì)時(shí)器中除了繪制彈幕的代碼還有執(zhí)行更新彈幕數(shù)組的代碼。
那么下面開(kāi)始直接上代碼:
(function () {
window.onload=function () {
var video = document.getElementsByTagName("video")[0]
var cav = document.getElementsByTagName("canvas")[0]
//設(shè)置常量canvas的高度以及寬度
var cavWidth = 800
var cavHeight = 420
cav.width=cavWidth
cav.height=cavHeight
var ctx = cav.getContext("2d")
//存儲(chǔ)彈幕對(duì)象的數(shù)組
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
//測(cè)試數(shù)據(jù)的數(shù)組
var testArrayCopy = []
var capobjId = 0
//彈幕在畫(huà)布中高度可能值組成的數(shù)組
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 測(cè)試數(shù)據(jù)
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:"老師說(shuō)的非常好,我要好好學(xué)習(xí)了》》》》",time:"12",ismove:true,colorIndex:0},
{content:"老師說(shuō)的非常好,我要好好學(xué)習(xí)了》》》》",time:"13",ismove:true,colorIndex:0},
{content:"老師說(shuō)的非常好,我要好好學(xué)習(xí)了》》》》",time:"14",ismove:true,colorIndex:2},
{content:"老師說(shuō)的非常好,我要好好學(xué)習(xí)了》》》》",time:"15",ismove:false,colorIndex:0},
{content:"老師說(shuō)的非常好,我要好好學(xué)習(xí)了》》》》",time:"16",ismove:true,colorIndex:2},
{content:"老師說(shuō)的非常好,我要好好學(xué)習(xí)了》》》》",time:"17",ismove:true,colorIndex:3},
{content:"老師說(shuō)的非常好,我要好好學(xué)習(xí)了》》》》",time:"18",ismove:true,colorIndex:2},
{content:"老師說(shuō)的非常好,我要好好學(xué)習(xí)了》》》》",time:"19",ismove:true,colorIndex:0},
{content:"老師說(shuō)的非常好,我要好好學(xué)習(xí)了》》》》",time:"20",ismove:true,colorIndex:3},
{content:"老師說(shuō)的非常好,我要好好學(xué)習(xí)了》》》》",time:"21",ismove:true,colorIndex:0},
{content:"老師說(shuō)的非常好,我要好好學(xué)習(xí)了》》》》",time:"22",ismove:true,colorIndex:0},
{content:"老鐵們,小禮物走一波了,小汽車(chē)小火箭刷起來(lái)吧=========",time:"23",ismove:true,colorIndex:0},
{content:"老鐵們,小禮物走一波了,小汽車(chē)小火箭刷起來(lái)吧=========",time:"24",ismove:true,colorIndex:0},
{content:"老鐵們,小禮物走一波了,小汽車(chē)小火箭刷起來(lái)吧=========",time:"25",ismove:true,colorIndex:3},
{content:"老鐵們,小禮物走一波了,小汽車(chē)小火箭刷起來(lái)吧=========",time:"26",ismove:true,colorIndex:0},
{content:"老鐵們,小禮物走一波了,小汽車(chē)小火箭刷起來(lái)吧=========",time:"27",ismove:true,colorIndex:5},
{content:"老鐵們,小禮物走一波了,小汽車(chē)小火箭刷起來(lái)吧=========",time:"28",ismove:false,colorIndex:5},
{content:"老鐵們,小禮物走一波了,小汽車(chē)小火箭刷起來(lái)吧=========",time:"29",ismove:true,colorIndex:5},
{content:"老鐵們,小禮物走一波了,小汽車(chē)小火箭刷起來(lái)吧=========",time:"30",ismove:true,colorIndex:5},
{content:"馬上就下課了,瓦羅藍(lán)大陸走起了~~~",time:"31",ismove:true,colorIndex:5},
{content:"馬上就下課了,瓦羅藍(lán)大陸走起了~~~",time:"32",ismove:true,colorIndex:2},
{content:"馬上就下課了,瓦羅藍(lán)大陸走起了~~~",time:"33",ismove:true,colorIndex:2},
{content:"馬上就下課了,瓦羅藍(lán)大陸走起了~~~",time:"33",ismove:true,colorIndex:5},
{content:"馬上就下課了,瓦羅藍(lán)大陸走起了~~~",time:"34",ismove:true,colorIndex:5},
{content:"馬上就下課了,瓦羅藍(lán)大陸走起了~~~",time:"35",ismove:true,colorIndex:5},
{content:"馬上就下課了,瓦羅藍(lán)大陸走起了~~~",time:"36",ismove:true,colorIndex:2},
{content:"馬上就下課了,瓦羅藍(lán)大陸走起了~~~",time:"37",ismove:true,colorIndex:2}]
//將測(cè)試數(shù)據(jù)備份
copyArray(testArray , testArrayCopy)
/*彈幕對(duì)象的構(gòu)造函數(shù),參數(shù)分別是:1.ismove:彈幕是否是移動(dòng)的彈幕,2.spe:彈幕的移動(dòng)速度,3.col:彈幕的顏色,4.text:彈幕的文本*/
/*原型鏈方法 setTopValue設(shè)置縱坐標(biāo),setLeftValue設(shè)置橫坐標(biāo),moving完成坐標(biāo)的改變,setId完成id值的設(shè)置*/
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()
//循環(huán)遍歷數(shù)組,根據(jù)對(duì)象的屬性繪制在畫(huà)布上
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
// }
}
}
//更新數(shù)組,當(dāng)對(duì)象已經(jīng)超出范圍的時(shí)候從數(shù)組刪除這個(gè)對(duì)象
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)
}
}
}
//更新保存彈幕對(duì)象的數(shù)組
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 ) {
//首次寫(xiě)的控制高度的方式,空間利用不充分,后來(lái)改為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)
}
}
}
//當(dāng)用戶點(diǎn)擊send發(fā)送彈幕的回調(diào)函數(shù)
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
// }
// }
//重新啟動(dòng)canvas,用在人為導(dǎo)致進(jìn)度條時(shí)間的改變
function reinitCav (argument) {
// testArray = testArrayCopy
copyArray(testArrayCopy , testArray)
capObjs = []
capHeight = 0
clearInterval(canvasTimer)
canvasTimer = null
initCanvas()
}
var canvasTimer = null
//初始化canvas,用在開(kāi)始播放時(shí)
function initCanvas () {
if (canvasTimer == null ) {
canvasTimer = setInterval(function (argument) {
drawAllText()
updateArray()
refreshObjs(capObjs)
},10)
}
}//end function initCanvas
//復(fù)制數(shù)組
function copyArray (arr1 , arr2) {
for (var i =0 , len=arr1.length ; i < len ; i++) {
arr2[i] = arr1[i]
}
}
//color select event 用戶發(fā)送彈幕的顏色控制代碼
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()
})
//進(jìn)度條改變執(zhí)行代碼
video.addEventListener("timeupdate", function () {
var nowPlayTime = video.currentTime
var diffTime = Math.abs(nowPlayTime - prevPlayTime)
prevPlayTime = nowPlayTime
if (diffTime > 1) {
reinitCav()
}
}, false)
//視頻暫停執(zhí)行代碼
video.addEventListener("pause" , function () {
clearInterval(canvasTimer)
canvasTimer = null
})
//點(diǎn)擊send的監(jiān)聽(tīng)事件
sendEle.addEventListener("click" , sendCaption)
//input的回車(chē)監(jiān)聽(tīng)事件
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
})()
相信看了這些案例你已經(jīng)掌握了方法,更多精彩請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!
相關(guān)閱讀:
HTML的table鼠標(biāo)拖拽排序該如何實(shí)現(xiàn)
HTML 5之新增的特性該如何使用
怎樣解決各種ie6-ie10的兼容問(wèn)題
以上就是h5怎樣通過(guò)canvas來(lái)實(shí)現(xiàn)滾動(dòng)彈幕功能的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!
網(wǎng)站建設(shè)是一個(gè)廣義的術(shù)語(yǔ),涵蓋了許多不同的技能和學(xué)科中所使用的生產(chǎn)和維護(hù)的網(wǎng)站。