Il n'y a pas de meilleur, seulement du meilleur. Comme le titre l'indique, cet article souhaite uniquement partager un effet de mouvement de particules obtenu à l'aide de Canvas. Cela ressemble un peu à un titre, mais d'un autre point de vue, cela peut à peine être considéré comme éblouissant. Bien que la couleur n'ait rien à voir avec l'éblouissement, l'effet de mouvement est quand même un peu éblouissant. Quoi qu'il en soit, commençons ce soi-disant effet éblouissant !
Accédez directement au code. Si vous ne comprenez pas, vous pouvez lire les commentaires du code. Vous comprendrez probablement l’idée générale.
code HTML
<!DOCTYPE html><html lang=fr><head><meta charset=UTF-8><title>Canvas permet d'obtenir des effets de mouvement de particules éblouissants - Front-end de la bibliothèque Cloud</title><style>* { margin: 0; : 0;}html,body { largeur : 100 % ; hauteur : 100 %;}canvas { affichage : bloc d'arrière-plan : #000;}body::-webkit-scrollbar{ display : aucun ;}.operator-box{ position : fixe ; haut : 0 ; gauche : 50 % ; bordure : 1px solide #fff ; arrière-plan : rgba(255,255,255,0.5); (-50 % ); transformer : traduireX(-50 %);}.back-type,.back-animate{ margin-right : 20px;}.flex-box{ display: flex; 0, 0,0.7) ; couleur : #fff ; taille de police : 16px ; bordure : aucune ; contour du texte : aucune ; 12px; box-shadow : inset 0 0 12px 1px rgba(0,0,0,0.7);}#input-text::placeholder{ couleur : #ccc ; hauteur de ligne : 55px ; hauteur : 55px;}select{ - apparence du kit Web : aucun ; -moz-apparence : aucun ; apparence : aucun ; remplissage : 0px 20px ; 0px 6px ; hauteur : 35px ; couleur : #fff ; alignement du texte : arrière-plan : rgba(0, 0, 0,0.7) url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAICAYAAAAx8TU7AAAAOUlEQ…R4gPgWEIMAiOYBCS4C8ZDAIrBq4gigNkztQEFMi6AuQHESAPMeXiEMiWfpAAAAAElFTkSuQmCC) non-répétition 190px 12px ; taille de l'arrière-plan : 5px 8px ; ombre de la boîte : encart 0 0 12px 1px rgba(0,0,0,0.7);}</style></head><body><div class=operator-box>< div class=flex-box> <div class=back-type>Type de spread : <select name= id=selectType> <option value=back>Return</option> <option value=auto>Aléatoire</option> </select> </div> <div class=back-animate>Effet de dispersion (efficace pour le homing) : <select class=back-dynamics id=selectDynamics> <option value= spring>dynamics.spring</option> <option value=bounce>dynamics.bounce</option> <option value=forceWithGravity>dynamics.forceWithGravity</option> <option value=gravity>dynamics.gravity</option> <option value=easeInOut>dynamics.easeInOut</option> <option value=easeIn>dynamics.easeIn</option> <option value=easeOut>dynamics.easeOut</option> option> <option value=linear>dynamics.linear</option> </select> </div> <div class=input-box><input type=text placeholder=Entrez les caractères chinois et appuyez sur Entrée id=input-text></div></div></div><script src=dynamics.min.js></script><script src=index.js></ script ><script>var iCircle = new Circle();</script></body></html>
Il n'y a pas beaucoup de code HTML, juste quelques éléments opérationnels. C’est facile à comprendre d’un coup d’œil ici. Pas besoin de gaspiller trop de mots. Jetons un coup d'œil au code JavaScript protagoniste de cet article. Cependant, avant de regarder le code, autant écouter l'idée d'obtenir cet effet :
Trois canevas sont utilisés dans le code JavaScript, this.iCanvas (page d'accueil), this.iCanvasCalculate (utilisé pour calculer la largeur du texte) et this.iCanvasPixel (utilisé pour dessiner du texte et obtenir les coordonnées de position des pixels correspondant au texte ) .
this.iCanvasCalculate et this.iCanvasPixel n'ont pas besoin d'être affichés sur la page, ce ne sont que des fonctions auxiliaires.
Voici le superbe code d'implémentation JS
function Circle() { var This = this; this.init(); this.generalRandomParam(); this.drawCircles(); this.ballAnimate(); this.getUserText(); Obtenez l'écran window.onresize = function(){ This.stateW = document.body.offsetWidth; This.stateH = document.body.offsetHeight This.iCanvasW = This.iCanvas.width = This.stateW; This.iCanvasH = This.iCanvas.height = This.stateH; This.ctx = This.iCanvas.getContext(2d);//Initialiser Circle.prototype.init = function( ){ //Largeur et hauteur de l'élément parent this.stateW = document.body.offsetWidth; this.stateH = document.body.offsetHeight; document.createElement(canvas); // Définit Canvas pour qu'il ait la même largeur et hauteur que l'élément parent this.iCanvasW = this.iCanvas.width = this.stateW; this.iCanvasH = this.iCanvas.height = this.stateH; // Obtenir l'environnement de peinture 2D this.ctx = this.iCanvas.getContext(2d); // Insérer dans l'élément de corps document.body.appendChild(this.iCanvas); this.iCanvasCalculate = document.createElement(canvas); // Toile utilisée pour enregistrer la largeur du texte calculée this.mCtx = this.iCanvasCalculate.getContext(2d); this.mCtx.font = 128px Microsoft Yahei; (toile); this.iCanvasPixel.setAttribute(style,position:absolute;top:0;left:0;); this.pCtx = null; // Toile utilisée pour dessiner du texte // Le nombre de cercles générés aléatoirement this.ballNumber = ramdomNumber(1000 , 2000); // Enregistre le tableau de toutes les balles this.balls = []; // Enregistre la dernière balle qui a arrêté de bouger dans l'animation this.animte = null; this.imageData = null; this.textWidth = 0; // Enregistre la largeur du texte généré this.textHeight = 150; // Enregistre la hauteur du texte généré this.inputText = ; this.actionCount = 0; this.ballActor = []; // Enregistre les particules qui génèrent le texte this.actorNumber = 0; // Enregistre le nombre de particules qui génèrent le texte this.backType = back; ; // Effet d'animation this.isPlay = false; // Logo (ne peut pas être généré lors de la génération de texte)}// Rendre tous les cercles Circle.prototype.drawCircles = function () { for(var i=0;i <this.ballNumber ;i++){ this.renderBall(this.balls[0]); }}// Obtenir le texte d'entrée de l'utilisateur Circle.prototype.getUserText = function(){ This = this; // Enregistrez ceci pour pointer vers ipu = document.getElementById(input-text); ipu.addEventListener(keydown,function(event){ if(event. Which === 13){ // Si c'est la touche Entrée ipu.value = ipu.value.trim(); // Supprimer les espaces de début et de fin var pat = /[/u4e00-/u9fa5]/ // Jugement chinois var isChinese = pat.test(ipu.value); if(ipu.value.length !=0 && isChinese){ This.inputText = ipu.value }else{ alert(Veuillez saisir des caractères chinois } if(This.isPlay); ) { return } This.getAnimateType(); This.getTextPixel(); This.isPlay = true } });}// Calculer la largeur du texte Circle.prototype.calculateTextWidth = function () { this.textWidth = this.mCtx.measureText(this.inputText).width;}// Obtenir les pixels du texte Circle.prototype.getTextPixel = function () { si( this.pCtx){ this.pCtx.clearRect(0,0,this.textWidth,this.textHeight); } this.calculateTextWidth(this.inputText); this.iCanvasPixel.width = this.iCanvasPixel.height = this.textHeight; .pCtx = this.iCanvasPixel.getContext(2d); this.pCtx.font = 128px Microsoft Yahei ; this.pCtx.fillStyle = #FF0000 ; this.pCtx.textBaseline = bottom ; this.pCtx.fillText(this.inputText,0,110); 0,0,this.textWidth,this.textHeight).data; this.getTextPixelPosition(this.textWidth,this.textHeight);}//Obtenir la position des pixels des particules de texte Circle.prototype.getTextPixelPosition = function (width,height) { var left = (this.iCanvasW - width)/2; = (this.iCanvasH - hauteur)/2; var espace = 4; this.actionCount = 0; i=0;i<this.textHeight;i+=space){ for(var j=0;j<this.textWidth;j+=space){ var index = j*space+i*this.textWidth*4; this.imageData[index] == 255){ if(this.actionCount<this.ballNumber){ this.balls[this.actionCount].status = 1; this.balls[this.actionCount].targetX = left+j; this.balls[this.actionCount].targetY = top+i; this.balls[this.actionCount].backX = this.balls[this.actionCount]. x; this.balls[this.actionCount].backY = this.balls[this.actionCount].y; this.ballActor.push(this.balls[this.actionCount]); } } } this.actorNumber = this.ballActor.length; } this.animateToText();}//La particule se déplace vers la position spécifiée Circle.prototype.animateToText = function(){ for(var i=0;i<This .actorNumber ;i++){dynamics.animate(This.ballActor[i], { x : this.ballActor[i].targetX, y : this.ballActor[i].targetY },{ type:dynamics.easeIn, duration: 1024, }); } setTimeout(function(){ This.ballbackType(); },3000);}//Les particules reviennent au Cercle le long du chemin d'origine .prototype.ballBackPosition = function(){ for(var i=0;i<This.actorNumber;i++){ var ball = This.ballActor[i];dynamics.animate(ball, { x : ball.backX, y : ball.backY },{ type :dynamics[this.backDynamics], durée : 991, complet :this.changeStatus(ball) } }}// Obtenir le type|effet d'animation Circle.prototype.getAnimateType = function() { var selectType = document.getElementById(selectType); var selectDynamics = document.getElementById(selectDynamics); this.backType = selectType.options[selectType.options.selectedIndex].value; this.backDynamics = selectDynamics.options[selectDynamics.options.selectedIndex].value;}//Réinitialiser le cercle de propagation .prototype.ballbackType = function(){ if(this.backType == retour){ this.ballBackPosition(); }else{ this.ballAutoPosition(); } this.ballActor = [];}// Dispersion aléatoire Circle.prototype.ballAutoPosition = function(ball){ for(var i= 0 ;i<this.actorNumber;i++){ this.changeStatus(this.ballActor[i]) }}// Changer l'état de la balle Circle.prototype.changeStatus = function(ball){ ball.status = 0; if(this.isPlay == true){ this.isPlay = false }}// Générer aléatoirement les paramètres pertinents de chaque cercle Circle; .prototype.generalRandomParam = function(){ for(var i=0;i<this.ballNumber;i++){ var ball = {}; Générer aléatoirement un rayon de cercle // Générer aléatoirement la coordonnée x du centre du cercle ball.x = ramdomNumber(0+ball.size, this.iCanvasW-ball.size); ball.y = ramdomNumber(0+ball.size, this.iCanvasH-ball); .size); ball.speedX = ramdomNumber(-1, 1); ball.speedY = ramdomNumber(-1, 1); ball.status = 0; ball.targetX = 0; ball.targetY = 0; ball.backX = 0; ball.backY = 0; }}// Changer la position du cercle Circle.prototype.changeposition = function(){ for( var i=0;i<this.ballNumber;i++){ if( this.balls[i].status == 0){ this.balls[i].x += this.balls[i].speedX; this.balls[i].y += this.balls[i].speedY; } }}// Dessine un cercle Circle.prototype.renderBall = function(ball){ this.ctx . fillStyle = #fff; this.ctx.beginPath(); // Ceci doit être ajouté avec this.ctx.arc(ball.x, ball.y, ball.size, 0, 2 * Math.PI); this.ctx.closePath(); // Ceci doit être ajouté avec this.ctx.fill();}// Jugement de collision de balle Circle.prototype.collision = function(ball){ for(var i= 0;i<this.ballNumber;i++){ if(ball.x>this.iCanvasW-ball.size || ball.x<ball.size){ if(ball.x>this.iCanvasW-ball.size){ ball.x = this.iCanvasW-ball.size; }else{ ball.x = ball.size } ball.speedX = - ball.speedX } if(ball.x>this.iCanvasW-ball.size){ ball.x = this.iCanvasW-ball.size; (ball.y>this.iCanvasH-ball.size || ball.y<ball.size){ if(ball.y>this.iCanvasH-ball.size){ ball.y = this.iCanvasH-ball.size; }else{ ball.y = ball.size; } ball.speedY = - ball.speedY; } }}// Démarrer l'animation Circle.prototype.ballAnimate = function(){ var This = this ; var animateFrame = window.requestAnimationFrame || window.msRequestAnimationFrame; (function move(){ animte = animateFrame(move); This.ctx.clearRect(0, 0, This.iCanvasW, This.iCanvasH); This.changeposition(); for(var i=0;i <This.ballNumber;i++){ This.collision(This.balls[i]); This.renderBall(This.balls[i] } })();}//Générer une fonction de nombre aléatoire ramdomNumber(min, max) { return Math.random() * (max - min) + min;}
Après avoir lu le code, je suppose que c'était juste un peu une frimerie, et cela ne vous a pas donné envie de faire ce truc. Pour cette raison, je sais que vous devez être convaincu par vos yeux. DÉMO en ligne : exemple de particules dynamiques.
Personne n’est parfait, et le code non plus. Il semble que le code qui fonctionne correctement présente également quelques défauts. Actuellement, cet effet ne prend en charge que le chinois. Quant à l’anglais, je dois travailler plus dur. Quoi qu’il en soit, l’anglais rejoindra certainement plus tard, ce n’est qu’une question de temps. Il y a aussi un attribut dans le code utilisé pour marquer si le texte généré peut être à nouveau exécuté : this.isPlay, ce qui est encore un petit défaut. Le changement d'état de this.isPlay ne change pas exactement au moment où les particules reviennent, mais change l'état à l'avance. Mais cet état n’affectera pas la mise en œuvre complète de l’effet de cet exemple.
Dans cet exemple, la bibliothèque Dynamics.js est utilisée, principalement pour utiliser certaines fonctions de mouvement afin de rendre les particules se déplacent de manière plus impressionnante, c'est tout.
Ce qui précède représente l’intégralité du contenu de cet article. J’espère qu’il sera utile à l’étude de chacun. J’espère également que tout le monde soutiendra le réseau VeVb Wulin.