Cet article présente principalement comment HTML utilise Canvas pour implémenter la fonction de barrage. J'espère qu'il sera utile à tout le monde.
Introduction
J'ai récemment eu besoin de faire un joueur de barrage alors que je faisais un gros travail. J'ai emprunté le code source d'autres personnes et en ai réimplémenté un moi-même. La démonstration est la suivante
Les principales fonctions sont<.>
Envoyer le barrageDéfinir la couleur, la vitesse et le type du barrage
Afficher le barrage
Défauts connus :
Ne peut pas être en plein écranLe canevas n'est pas adaptatifIl n'y a pas de contrôle personnalisé du joueur
Le barrage correspondant ne s'affiche pas en fonction du temps de lecture
Le barrage ne peut pas être survolé
Les défauts déjà connus seront améliorés à l'avenir. Les codes sources des joueurs de barrage que l'on peut trouver sur Internet ne font généralement que des barrages roulants et non des barrages statiques. Ici j'ai spécialement ajouté l'implémentation du barrage statique.
Canvas dessine du texte et un effet de défilement de texte
Le cœur de l'ensemble du lecteur est de dessiner du texte et d'animer le défilement du texte pour le texte dans le canevas. Il n'existe pas de bon support d'animation, vous ne pouvez donc l'implémenter que par vous-même. L'idée de l'implémenter est d'effacer constamment l'écran, puis de réécrire le texte. Lorsque la fréquence d'effacement et de réécriture de l'écran atteint 24 ips, l'animation est fluide. sera atteint. Ajoutez d'abord la balise vidéo vidéo et la balise canevas au fichier HTML<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>
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; } } } }
Une fois la construction de l'objet barrage terminée, entrez le thème et la production d'animation, entrez directement le code
//循环擦写画布实现动画效果 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; } } }
Résumé
Ce projet utilise principalement un canevas pour le dessin de texte et l'animation d'assouplissement de texte. Les principales méthodes utilisées sont<. 🎜>canvasDom.getContext() canvas.save()/canvas.restore() canvas.clearRect() canvas.moveTo()
À l'origine, je ne comprenais pas save() et restaurer(), mais maintenant j'ai un peu compris. Lorsque vous changez l'état du canevas, le canevas actuel n'est plus le canevas actuel. toile d'origine, donc avant de modifier l'état du canevas, enregistrez l'état du canevas et changez d'état du canevas. Après avoir terminé le travail, revenez à l'état du canevas d'origine et continuez à travailler. Par exemple, lorsque je gère des barrages statiques et que je change le point de base du canevas, la méthode de nettoyage du canevas d'origine ne s'applique plus au canevas actuel et je ne peux utiliser qu'une autre méthode de nettoyage dans le canevas actuel. Revenez ensuite à la toile d'origine.
Code exécutable
<!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>
Résumé : ce qui précède est l'intégralité du contenu de cet article, j'espère qu'il sera utile à l'étude de chacun .
Recommandations associées :
Explication détaillée du cas d'utilisation de H5+Canvas
Comment utiliser Vue+canvas pour implémenter la fonction de bloc d'écriture mobile
js+canvasimplémente la fonction de code de vérification du puzzle coulissant
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!