HTML怎样应用canvas实现弹幕功能
简介
比来在做大作业的时候需要做一个弹幕播放器。借鉴了一下别人的源码本人从新实现了一个,演示如下
主要的功效有
发送弹幕
设定弹幕的色彩,速度和类型
显示弹幕
已知缺陷:
不克不及全屏
canvas没有做自顺应
没有自定义播放器控件
没有按照播放时间显示响应的弹幕
弹幕不克不及实现悬停
已知的缺陷今后会停止改善。网上能寻到的弹幕播放器的源码一样只做了滚动的弹幕而没有做静止的弹幕,这里我特地加上了静止弹幕的实现。
Canvas绘制文字乃至文字滚动结果
整个播放器的中心就是绘制文字乃至做文字滚动的动画,canvas中关于文字并没有很好的动画支撑,只能通过本人实现,实现的思绪就是不竭的清屏然后重写文字,当清屏重写的频率到达24fps的时候就是流畅的动画了。
先在HTML文件中增加视频video标签和画布canvas标签
<p id="barrageplayer"> <canvas id="cv_video" width="900px" height="450px"></canvas> <video id="v_video" src="test.MP4" controls type="video/mp4"></video> </p>
把canvas标签的位置样式设定为position:absolute然后视频和画布就重叠在一起,看起来就是一个弹幕播放器了。然后为画布增加弹幕相关的内容,第一猎取画布的相关信息和设定画布的字体大小和字体样式
var c=document.getElementById("cv_video"); //猎取画布大小 var c_height=c.height; var c_width=c.width; //猎取画布 ctx=c.getContext("2d"); //设定字体样式 ctx.font="25px DengXian"; 画布信息已经猎取和设定,巧妇难为无米之炊,接着我们就要结构弹幕对象,使用的结构模式是动态原型模式 //弹幕对象 function Barrage(content,color,type,speed){ this.content=content; this.color=color; this.type=type; this.speed=speed; if(this.type=="default"){ this.height=parseInt(Math.random()*c_height)+10; }else if (this.type=="static top"){ this.height=parseInt((c_height/2)-Math.random()*c_height/2)+10; }else if (this.type=="static bottom"){ this.height=parseInt((c_height/2)+Math.random()*c_height/2)+10; } if(typeof this.move!="function"){ Barrage.prototype.move=function(){ if(this.type=="default"){ this.left=this.left-this.speed; } } } }
结构的弹幕对象初始化了各种参数,包罗内容,色彩,运动类型和速度,定义了move()办法来操纵弹幕的缓动,每动身一次move()办法向左滚动一个单位speed的像素。
弹幕对象结构完成之后就进入到主题,动画的制作,直接上代码
//轮回擦写画布实现动画结果 setInterval(function(){ ctx.clearRect(0,0,c_width,c_height); ctx.save(); for(var i=0;i<msgs.length;i++){ if(msgs[i]!=null){ if(msgs[i].type=="default"){ handleDefault(msgs[i]); }else{ handleStatic(msgs[i]); } } } },20)
每20ms施行一次擦写,ctx.clearRect(0,0,c_width,c_height);是将整张当前的画布清除,然后使用ctx.save()将当前的画布留存,接着遍历弹幕列表(msgs是弹幕列表,当每发送一条弹幕都会将该弹幕实例增加到列表中),然后依照默许样式的弹幕还是静止样式的弹幕离别处置。假如是默许样式的弹幕将会依照以下的办法处置
//处置默许弹幕样式 function handleDefault(barrage){ if(barrage.left==undefined||barrage.left==null){ barrage.left=c.width; }else{ if(barrage.left<-200){ barrage=null; }else{ barrage.move() ctx.fillStyle=barrage.color; ctx.fillText(barrage.content,barrage.left,barrage.height) ctx.restore(); } } }
第一假如弹幕实例没有设定left属性则将画布的宽度给予它,假如弹幕实例已经退出画布则将其置null以节约内存,不然的话就调取弹幕实例的move()办法改动left属性的值,然后设定文字的色彩,1级写入新的文字,复原画布。这样就完成了一帧动画。
关于静止弹幕的实现办法如下
//处置静止弹幕样式 function handleStatic(barrage){ ctx.moveTo(c_width/2,barrage.height); ctx.textAlign="center"; ctx.fillStyle=barrage.color; ctx.fillText(barrage.content,c_width/2,barrage.height); if(barrage.left==undefined||barrage.left==null){ barrage.left=c.width; }else{ if(barrage.left<-200){ ctx.fillText("",c_width/2,barrage.height); barrage=null; //ctx.restore(); ctx.clearRect(0,0,c_width,c_height); }else{ barrage.left=barrage.left-6; } } }
第一将画布的基点移动到画布的中心,需要留意的是这时候相对与生成了一张新的画布,本来画布的clearRect()办法已经不适用与这张画布了。然后再设定文字对齐为居中对齐,设定文字样式,填充文字。由于弹幕是静止的所以不需要停止缓动,但是静止弹幕也是会消逝的,需要设定一个标记位来使他按时消逝。在这里为了不占用额外的属性,我们直接使用left属性作为标记位,一样停止left属性的递减,但不把递减反映到画布中,当left到达阈值,则使用ctx.clearRect()办法将弹幕清除。这样就实现了静止弹幕的处置。
其他关于色彩,样式的设定有必然根基的人应当是很容易把握的在这里就不多介绍了,本人看可运转代码部分懂得一下就好。
总结
这个项目主如果使用了canvas停止文字绘制乃至实现文字的缓动动画,主要用到的办法有
canvasDom.getContext() canvas.save()/canvas.restore() canvas.clearRect() canvas.moveTo()
本来我对与save()和restore()是不克不及懂得的,此刻我算是有一点懂得了,当你更换了画布状态,此刻的画布就已经不是本来的画布,所以在修改画布状态此前先把画布状态留存,切换画布状态,完成工作之后,复原为本来的画布状态连续工作。像我处置静态弹幕的时候,把画布的基点改动了,那么本来画布的清除办法就不再适用于当前画布,只要在当前画布中本人使用别的的清除办法。然后再复原到本来的画布。
可运转代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <style type="text/css"> .pickp{ width: 30px; height: 30px; cursor: pointer; border: 2px solid gray; display: inline-block; } #white{ background: white; } #red{ background:#ff6666; } #yellow{ background:#ffff00; } #blue{ background:#333399; } #green{ background:#339933; } #cv_video{ position: absolute; z-index: 1; } #barrageplayer{ position: relative; display: block; width: 900px; height: 500px; } #v_video{ position: absolute; width: 100%; height: 100%; z-index: 0; } </style> <body> <p id="barrageplayer"> <canvas id="cv_video" width="900px" height="450px"></canvas> <video id="v_video" src="test.MP4" controls type="video/mp4"></video> </p> <p id="barrageinput"> <p> <input type="text" id="smsg" placeholder="请输入弹幕内容"/> <button id="send"> 发送</button> </p> <p id="colorpick"> <p class="pickp" id="white"></p> <p class="pickp" id="red"></p> <p class="pickp" id="yellow"></p> <p class="pickp" id="blue"></p> <p class="pickp" id="green"></p> </p> <p id="typepick"> <input type="radio" name="type" value="default">默许 <input type="radio" name="type" value="static top">静止顶部 <input type="radio" name="type" value="static bottom">静止底部 </p> <p id="speedpick"> <input type="radio" name="speed" value="1">1X <input type="radio" name="speed" value="2">2X <input type="radio" name="speed" value="3">3X </p> <p id="stylepick"></p> </p> <script> var c=document.getElementById("cv_video"); var typeDom=document.getElementsByName("type"); var speedDom=document.getElementsByName("speed"); var colorpick=document.getElementById("colorpick"); var smsg=document.getElementById("smsg"); var color="#white"; var speed=1; var type="default"; var msgs=[]; //猎取画布大小 var c_height=c.height; var c_width=c.width; //猎取画布 ctx=c.getContext("2d"); ctx.font="25px DengXian"; //处置色彩选中 colorpick.addEventListener('click',function(event){ switch(event.target.id){ case "white": color="white"; break; case "red": color="#ff6666"; break; case "yellow": color="#ffff00"; break; case "green": color="#339933"; break; case "blue": color="#333399"; break; } }) //处置发送弹幕 document.getElementById("send").onclick=function(){ var text=smsg.value; for(var i=0;i<typeDom.length;i++){ if(typeDom[i].checked){ type=typeDom[i].value; break; } } for(var i=0;i<speedDom.length;i++){ if(speedDom[i].checked){ speed=2*parseInt(speedDom[i].value); break; } } var tempBarrage=new Barrage(text,color,type,speed); msgs.push(tempBarrage); } // //弹幕功效部分代码 // //弹幕对象 function Barrage(content,color,type,speed){ this.content=content; this.color=color; this.type=type; this.speed=speed; if(this.type=="default"){ this.height=parseInt(Math.random()*c_height)+10; }else if (this.type=="static top"){ this.height=parseInt((c_height/2)-Math.random()*c_height/2)+10; }else if (this.type=="static bottom"){ this.height=parseInt((c_height/2)+Math.random()*c_height/2)+10; } if(typeof this.move!="function"){ Barrage.prototype.move=function(){ if(this.type=="default"){ this.left=this.left-this.speed; } } } } //轮回擦写画布实现动画结果 setInterval(function(){ ctx.clearRect(0,0,c_width,c_height); ctx.save(); for(var i=0;i<msgs.length;i++){ if(msgs[i]!=null){ if(msgs[i].type=="default"){ handleDefault(msgs[i]); }else{ handleStatic(msgs[i]); } } } },20) //处置默许弹幕样式 function handleDefault(barrage){ if(barrage.left==undefined||barrage.left==null){ barrage.left=c.width; }else{ if(barrage.left<-200){ barrage=null; }else{ barrage.move() ctx.fillStyle=barrage.color; ctx.fillText(barrage.content,barrage.left,barrage.height) ctx.restore(); } } } //处置静止弹幕样式 function handleStatic(barrage){ ctx.moveTo(c_width/2,barrage.height); ctx.textAlign="center"; ctx.fillStyle=barrage.color; ctx.fillText(barrage.content,c_width/2,barrage.height); if(barrage.left==undefined||barrage.left==null){ barrage.left=c.width; }else{ if(barrage.left<-200){ ctx.fillText("",c_width/2,barrage.height); barrage=null; //ctx.restore(); ctx.clearRect(0,0,c_width,c_height); }else{ barrage.left=barrage.left-6; } } } </script> </body> </html>
总结:以上就是本篇文的全部内容,但愿能对大家的学习有所帮忙。
相关引荐:
H5+Canvas使用案例详解
怎样使用Vue+canvas实现移动端手写板功效
js+canvas实现滑动拼图验证码功效
以上就是HTML怎样利用canvas实现弹幕功效的具体内容,更多请关注百分百源码网其它相关文章!