这次给大家带来使用canvas实现视频里的弹幕效果,使用canvas实现视频弹幕效果的注意事项有哪些,下面就是实战案例,一起来看一下。
最近在着手开发弹幕视频网站,通过html5中的canvas实现了弹幕的功能。
那么闲言碎语不要讲,先说思路后上代码。
思路:从页面布局上来说就是将一块画布覆盖在了video标签产生的视频窗口之上,使用绝对定位就能实现了。最重要的就是js控制画布上弹幕的显示了,每一个弹幕都包装成一个对象,对象包含的属性有弹幕应该出现的时间,弹幕的颜色,弹幕是否是移动的以及弹幕的文本。弹幕对象拥有方法包含:设置弹幕的横纵坐标,弹幕的移动函数。实现的原理,在监听视频开始播放的事件,在视频开始播放时生成一个定时器,定时器每隔一个时间去遍历循环弹幕对象数组并根据对象的属性在画布的适当位置上绘制出弹幕,计时器中除了绘制弹幕的代码还有执行更新弹幕数组的代码。
下图是弹幕效果截屏
那么下面开始直接上代码:
复制代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
(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
})()
登录后复制
相信看了本文案例你已经掌握了方法,更多精彩请关注靠谱客其它相关文章!
推荐阅读:
H5实现可缩放的时钟动画
Drag事件编辑器实现拖拽上传图片效果
以上就是使用canvas实现视频里的弹幕效果的详细内容,更多请关注靠谱客其它相关文章!
最后
以上就是疯狂心锁最近收集整理的关于使用canvas实现视频里的弹幕效果的全部内容,更多相关使用canvas实现视频里内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复