Cette fois, je vais vous apporter une explication détaillée de la création d'une animation de grille de particules dynamique avec Canvas. Quelles sont les précautions pour créer une animation de grille de particules dynamique avec Canvas. .
J'ai récemment vu une animation de grille de particules très sympa, alors j'en ai créé une moi-même. Elle fonctionne bien comme arrière-plan. Le CSDN ne peut pas télécharger d'images dépassant 2 Mo, je coupe donc simplement une image statique :
Commençons par comment obtenir cet effet :
Tout d'abord, de Bien sûr Il est temps d'ajouter un canevas :
<canvas></canvas>
Voici le style :
<style> #canvas{ position: absolute; display: block; left:0; top:0; background: #0f0f0f; z-index: -1; } </style>
Le z-index du canevas ci-dessus : -1 peut être placé sous certains éléments comme un arrière-plan.
Afin de garantir que le canevas puisse remplir tout le navigateur, la largeur et la hauteur du canevas doivent être définies pour être les mêmes que celles du navigateur :
function getSize(){ w = canvas.width = window.innerWidth; h = canvas.height = window.innerHeight; }
Le w et le h ci-dessus représentent respectivement la largeur et la hauteur du navigateur.
Après avoir obtenu la largeur et la hauteur du navigateur, l'étape suivante consiste à dessiner les particules à l'intérieur. Ici, nous devons définir certains paramètres de particules à l'avance :
var opt = { particleAmount: 50, //粒子个数 defaultSpeed: 1, //粒子运动速度 variantSpeed: 1, //粒子运动速度的变量 particleColor: "rgb(32,245,245)", //粒子的颜色 lineColor:"rgb(32,245,245)", //网格连线的颜色 defaultRadius: 2, //粒子半径 variantRadius: 2, //粒子半径的变量 minDistance: 200 //粒子之间连线的最小距离 };
Les variables de vitesse ci-dessus et. les variables de rayon sont les deux. Cela permet de garantir que la taille et la vitesse des particules ne sont pas exactement les mêmes.
Ensuite on crée une classe pour initialiser les particules. Le code est relativement long, j'ai donc ajouté des commentaires :
function Partical(){ this.x = Math.random()*w; //粒子的x轴坐标 this.y = Math.random()*h; //粒子的y轴坐标 this.speed = opt.defaultSpeed + opt.variantSpeed*Math.random(); //粒子的运动速度 this.directionAngle = Math.floor(Math.random()*360); //粒子运动的方向 this.color = opt.particleColor ; //粒子的颜色 this.radius = opt.defaultRadius+Math.random()*opt.variantRadius; //粒子的半径大小 this.vector = { x:this.speed * Math.cos(this.directionAngle), //粒子在x轴的速度 y:this.speed * Math.sin(this.directionAngle) //粒子在y轴的速度 } this.update = function(){ //粒子的更新函数 this.border(); //判断粒子是否到了边界 this.x += this.vector.x; //粒子下一时刻在x轴的坐标 this.y += this.vector.y; //粒子下一时刻在y轴的坐标 } this.border = function(){ //判断粒子是都到达边界 if(this.x >= w || this.x= h || this.y w){ //下面是改变浏览器窗口大小时的操作,改变窗口大小后有的粒子会被隐藏,让他显示出来即可 this.x = w; } if(this.y > h){ this.y = h; } if(this.x <p style="text-align: left;">1 La vitesse et l'angle initiaux de chaque particule sont générés aléatoirement. , la couleur des particules est déterminée par les options de réglage correspondantes. </p><p style="text-align: left;">2. This.vector est utilisé pour stocker la direction de mouvement des particules : si this.vector.x vaut 1, les particules se déplacent vers la droite ; s'il vaut -1, les particules se déplacent vers la gauche. De même, si this.vector.y est négatif, la particule se déplace vers le haut, et s'il est positif, la particule se déplace vers le bas. </p><p style="text-align: left;">This.update est utilisé pour mettre à jour les coordonnées de la prochaine position de chaque particule. Tout d'abord, la détection des bords est effectuée ; si le mouvement de la particule dépasse la taille du canevas, le vecteur de direction est multiplié par -1 pour produire la direction de mouvement opposée. </p><p style="text-align: left;">3. La mise à l'échelle de la fenêtre peut amener les particules à dépasser la limite, de sorte que la fonction de détection des bords ne peut pas les capturer, donc une série d'instructions if sont nécessaires pour détecter cette situation et réinitialiser la position des particules à la frontière actuelle. de la toile. </p><p style="text-align: left;">4. La dernière étape consiste à dessiner ces points sur la toile. </p><p style="text-align: left;">La classe de particules a été écrite, dessinons-la : </p><pre class="brush:php;toolbar:false">function init(){ getSize(); for(let i = 0;i<opt.particleamount><p style="text-align: left;">Les objets particules opt.particleAmount sont initialisés au-dessus, et les objets sont initialisés mais pas dessinés en dessous. C'est la boucle. function : </p> <pre class="brush:php;toolbar:false">function loop(){ ctx.clearRect(0,0,w,h); for(let i = 0;i<particle.length><p style="text-align: left;">Chaque fois que la fonction loop() est exécutée, le contenu sur le canevas sera effacé, puis les coordonnées des particules seront recalculées via la fonction update() de l'objet particule , et enfin via la fonction draw() de la fonction objet particule ) pour dessiner des particules. Voici l'effet à ce moment : </p><p style="text-align: left;"><img title="" alt="Explication détaillée de la création dune animation de grille de particules dynamique avec Canvas" src="https://img.php.cn/upload/article/000/061/021/c0c9b9891fd6ff9bfb9f8bad2673271e-1.gif"></p><p style="max-width:90%">Mais certaines particules disparaîtront après le changement de taille de la fenêtre du navigateur. À ce moment, vous devez ajouter un événement pour surveiller si le. la taille du navigateur change. :</p><pre class="brush:php;toolbar:false">window.addEventListener("resize",function(){ winResize() },false);
Ensuite, vous devez écrire la fonction winResize(). Il convient de noter ici que l'événement de redimensionnement sera déclenché très fréquemment lorsque le navigateur change. légèrement le navigateur, l'événement de redimensionnement sera déclenché des dizaines de fois, puis la taille du navigateur sera recalculée des dizaines de fois, ce qui consomme des performances. Parlons simplement de la solution ici. juste la taille finale du navigateur après le changement. Quant au milieu, cela n'a rien à voir avec nous combien de fois il a été modifié, nous pouvons donc retarder l'événement de calcul de la taille du navigateur de 200 millisecondes lorsque la fenêtre du navigateur change. Si l'événement de redimensionnement est déclenché pendant cette période, alors il sera retardé de 200 millisecondes. Cela semble compliqué, mais le code est en réalité très simple :
var particle = [], w,h; //粒子数组,浏览器宽高 var delay = 200,tid; //延缓执行事件和setTimeout事件引用 function winResize(){ clearTimeout(tid); tid = setTimeout(function(){ getSize(); //获取浏览器宽高,在文章最上面有介绍 },delay) }
De cette façon, toutes les animations de particules sont terminées. Ensuite, vous pouvez tracer des lignes entre les particules. Il y a une minDistance dans l'objet opt que nous avons défini ci-dessus, lorsque la ligne entre deux particules est inférieure à cette valeur, nous traçons une ligne entre elles.
Alors, comment calculer la distance entre deux particules ? Vous vous souvenez de la première leçon de mathématiques du collège, le théorème de Pythagore : la somme des carrés des deux côtés rectangles d'un triangle rectangle. est égal au carré de la troisième variable Voir ci-dessous :
我们现在知道每个粒子的x轴和y轴的坐标,那么我们就可以计算出两个点之间的距离了,写一个函数,传入两个点,如下:
function getDistance(point1,point2){ return Math.sqrt(Math.pow(point1.x-point2.x,2) + Math.pow(point1.y - point2.y ,2)); }
现在我们可以计算出两个点的距离,那么我们就计算出所有每个粒子同其他所有粒子的距离,来确定它们之间是否需要连线,当然如果所有粒子的颜色深度都一模一样,那就有点丑了,所以我们这里可以根据两个粒子之间的距离来决定连线的透明度,两个粒子距离越近,越不透明,距离越远,越透明,超过一定距离就不显示了。
function linePoint(point,hub){ for(let i = 0;i<hub.length> 0){ ctx.lineWidth = 0.5; ctx.strokeStyle = "rgba("+line[0]+","+line[1]+","+line[2]+","+opacity+")"; ctx.beginPath(); ctx.moveTo(point.x,point.y); ctx.lineTo(hub[i].x,hub[i].y); ctx.closePath(); ctx.stroke(); } } }</hub.length>
上面传入的两个参数分别是一个点和整个点的数组,let opacity = 1 -distance/opt.minDistance;用于判断连线之间的透明度同时也判断了距离,距离大于opt.minDistance时,opacity为负,下面判断时就过滤掉了,上面的颜色用到了正则表达式,需要先解析最上面opt对象里给出的颜色,然后再加上透明度,这段代码如下:
var line = opt.lineColor.match(/\d+/g);
最后在loop()函数里面不断循环计算距离就可以了,在loop()中加入代码后如下:
function loop(){ ctx.clearRect(0,0,w,h); for(let i = 0;i需要指出的是:如果添加过多的点和/或过多的连接距离(连接距离会创建过多的线条),动画也会扛不住。当视口变窄时最好降低粒子的运动速度:粒子的尺寸越小,在愈加狭窄空间内的移动速度貌似会越快。
显示整段代码:
nbsp;html>canvasExplication détaillée de la création dune animation de grille de particules dynamique avec Canvas <canvas></canvas> <script> var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); var opt = { particleAmount: 50, //粒子个数 defaultSpeed: 1, //粒子运动速度 variantSpeed: 1, //粒子运动速度的变量 particleColor: "rgb(32,245,245)", //粒子的颜色 lineColor:"rgb(32,245,245)", //网格连线的颜色 defaultRadius: 2, //粒子半径 variantRadius: 2, //粒子半径的变量 minDistance: 200 //粒子之间连线的最小距离 }; var line = opt.lineColor.match(/\d+/g); console.log(line); var particle = [], w,h; var delay = 200,tid; init(); window.addEventListener("resize",function(){ winResize() },false); function winResize(){ clearTimeout(tid); tid = setTimeout(function(){ getSize(); },delay) } function init(){ getSize(); for(let i = 0;i<opt.particleAmount; i++){ particle.push(new Partical()); } loop(); } function loop(){ ctx.clearRect(0,0,w,h); for(let i = 0;i<particle.length; i++){ particle[i].update(); particle[i].draw(); } for(let i = 0;i<particle.length; i++){ linePoint(particle[i],particle) } window.requestAnimationFrame(loop); } function linePoint(point,hub){ for(let i = 0;i<hub.length;i++){ let distance = getDistance(point,hub[i]); let opacity = 1 -distance/opt.minDistance; if(opacity > 0){ ctx.lineWidth = 0.5; ctx.strokeStyle = "rgba("+line[0]+","+line[1]+","+line[2]+","+opacity+")"; ctx.beginPath(); ctx.moveTo(point.x,point.y); ctx.lineTo(hub[i].x,hub[i].y); ctx.closePath(); ctx.stroke(); } } } function getDistance(point1,point2){ return Math.sqrt(Math.pow(point1.x-point2.x,2) + Math.pow(point1.y - point2.y ,2)); } function getSize(){ w = canvas.width = window.innerWidth; h = canvas.height = window.innerHeight; } function Partical(){ this.x = Math.random()*w; //粒子的x轴坐标 this.y = Math.random()*h; //粒子的y轴坐标 this.speed = opt.defaultSpeed + opt.variantSpeed*Math.random(); //粒子的运动速度 this.directionAngle = Math.floor(Math.random()*360); //粒子运动的方向 this.color = opt.particleColor ; //粒子的颜色 this.radius = opt.defaultRadius+Math.random()*opt.variantRadius; //粒子的半径大小 this.vector = { x:this.speed * Math.cos(this.directionAngle), //粒子在x轴的速度 y:this.speed * Math.sin(this.directionAngle) //粒子在y轴的速度 } this.update = function(){ //粒子的更新函数 this.border(); //判断粒子是否到了边界 this.x += this.vector.x; //粒子下一时刻在x轴的坐标 this.y += this.vector.y; //粒子下一时刻在y轴的坐标 } this.border = function(){ //判断粒子是都到达边界 if(this.x >= w || this.x<= 0){ //如果到达左右边界,就让x轴的速度变为原来的负数 this.vector.x *= -1; } if(this.y >= h || this.y <= 0){ //如果到达上下边界,就让y轴的速度变为原来的负数 this.vector.y *= -1; } if(this.x > w){ //下面是改变浏览器窗口大小时的操作,改变窗口大小后有的粒子会被隐藏,让他显示出来即可 this.x = w; } if(this.y > h){ this.y = h; } if(this.x < 0){ this.x = 0; } if(this.y < 0){ this.y = 0; } } this.draw = function(){ //绘制粒子的函数 ctx.beginPath(); ctx.arc(this.x, this.y, this.radius ,0 ,Math.PI * 2); ctx.closePath(); ctx.fillStyle = this.color; ctx.fill(); } } </script>Copier après la connexion
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
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!