Não existe melhor, apenas melhor. Como o título indica, este artigo deseja apenas compartilhar um efeito de movimento de partículas obtido usando o Canvas. Parece uma manchete, mas de outra perspectiva, dificilmente pode ser considerado deslumbrante. Embora a cor não tenha nada a ver com deslumbrante, o efeito do movimento ainda é um pouco deslumbrante. De qualquer forma, vamos começar esse chamado efeito deslumbrante!
Vá diretamente para o código. Se não entender, você pode ler os comentários do código. Você provavelmente entenderá a ideia geral.
código HTML
<!DOCTYPE html><html lang=en><head><meta charset=UTF-8><title>O Canvas obtém efeitos deslumbrantes de movimento de partículas - Front end da biblioteca em nuvem</title><style>* { margin: 0; : 0;}html,body { largura: 100%; altura: 100%;}canvas { display: block; background: #000;}body::-webkit-scrollbar{ display: nenhum;}.operator-box{posição: fixo superior: 0; borda esquerda: 1px sólido #fff; (-50%); transform: translateX(-50%);}.back-type,.back-animate{margem-direita: 20px;}.flex-box{ display: flex; justificar-conteúdo: centro; alinhar itens: centro;}#input-text{ altura da linha: 35px largura: 260px altura: 35px; 0, 0,0,7); cor: #fff; tamanho da fonte: 16px; contorno: nenhum; 12px; box-shadow: inserção 0 0 12px 1px rgba(0,0,0,0.7);}#input-text::placeholder{ cor: #ccc; altura da linha: 55px altura: 55px;}select{ - aparência do webkit: nenhuma; -moz-aparência: nenhuma aparência: nenhuma borda: nenhuma; 0px 6px; altura: 35px cor: #fff; alinhamento de texto: fundo: rgba(0, 0, 0,0,7) url (dados:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAICAYAAAAx8TU7AAAAOUlEQ…R4gPgWEIMAiOYBCS4C8ZDAIrBq4gigNkztQEFMi6AuQHESAPMeXiEMiWfpAAAAAElFTkSuQmCC) sem repetição 190px 12px; tamanho do fundo: 5px 8px; box-shadow: inserção 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>Tipo de spread: <select name= id=selectType> <option value=back>Return</option> <option value=auto>Aleatório</option> </select> </div> <div class=back-animate>Efeito de dispersão (eficaz para 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</ opção> <option value=linear>dynamics.linear</option> </select> </div> <div class=input-box><input type=text placeholder=Insira caracteres chineses e pressione Enter 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>
Não há muito código HTML, apenas alguns elementos operacionais. É fácil entender rapidamente aqui. Não há necessidade de desperdiçar muitas palavras. Vamos dar uma olhada no código JavaScript protagonista deste artigo. No entanto, antes de olhar para o código, podemos também ouvir a ideia de obter este efeito:
Três telas Canvas são usadas no código JavaScript, this.iCanvas (página inicial), this.iCanvasCalculate (usada para calcular a largura do texto), this.iCanvasPixel (usada para desenhar texto e obter as coordenadas de posição dos pixels correspondentes ao texto ).
this.iCanvasCalculate e this.iCanvasPixel não precisam ser exibidos na página, são apenas funções auxiliares.
Aqui está o incrível código de implementação JS
function Circle() { var This = this; this.init(); this.generalRandomParam(); this.drawCircles(); Obtenha a tela window.onresize = function(){ This.stateW = document.body.offsetWidth; This.stateH = document.body.offsetHeight; This.iCanvas.width = This.stateW; This.iCanvasH = This.iCanvas.height = This.stateH; ){ //Largura e altura do elemento pai this.stateW = document.body.offsetWidth; this.stateH = document.body.offsetHeight; document.createElement(canvas); // Defina o Canvas para ter a mesma largura e altura do elemento pai this.iCanvasW = this.iCanvas.width = this.stateW; // Obtenha o ambiente de pintura 2D this.ctx = this.iCanvas.getContext(2d); // Insira no elemento do corpo document.body.appendChild(this.iCanvas); this.iCanvasCalculate = document.createElement(canvas); // Tela usada para salvar a largura do texto calculado this.mCtx = this.iCanvasCalculate.getContext(2d); (tela); this.iCanvasPixel.setAttribute(style,position:absolute;top:0;left:0;); this.pCtx = null; // Tela usada para desenhar texto // O número de círculos gerados aleatoriamente this.ballNumber = ramdomNumber(1000 , 2000); // Salva um array de todas as bolas this.balls = []; // Salva a última bola que parou de se mover na animação this.animte = null; this.imageData = null; this.textWidth = 0; // Salva a largura do texto gerado this.textHeight = 150; // Salva a altura do texto gerado this.inputText = ; this.actionCount = 0; this.ballActor = []; // Salva as partículas que geram o texto this.backDynamics = 0; ; // Efeito de animação this.isPlay = false; // Logotipo (não pode ser gerado durante a geração de texto)}// Renderizar todos os círculos Circle.prototype.drawCircles = function () { for(var i=0;i <this.ballNumber ;i++){ this.renderBall(this.balls[0]);// Obtém o texto de entrada do usuário Circle.prototype.getUserText = function(){ This = this; // Salve isso para apontar para ipu = document.getElementById(input-text); // Se for a tecla enter ipu.value = ipu.value.trim(); // Remove espaços iniciais e finais var pat = /[/u4e00-/u9fa5]/ // Julgamento chinês var isChinese = pat.test(ipu.value); if(ipu.value.length !=0 && isChinese){ This.inputText = }else{ alert(Insira caracteres chineses return } if(This.isPlay); ) { return } This.getAnimateType(); This.getTextPixel(); Calcule a largura do texto Circle.prototype.calculateTextWidth = function () { this.textWidth = this.mCtx.measureText(this.inputText).width;}// Obtenha os pixels do texto Circle.prototype.getTextPixel = function () { se(este.pCtx){ this.pCtx.clearRect(0,0,this.textWidth,this.textHeight } this.calculateTextWidth(this.inputText); .pCtx = this.iCanvasPixel.getContext(2d); this.pCtx.font = 128px Microsoft Yahei; this.pCtx.fillStyle = #FF0000; this.pCtx.textBaseline = this.pCtx.fillText (this.inputText,0,110); 0,0,this.textWidth,this.textHeight).dados; this.getTextPixelPosition(this.textWidth,this.textHeight);}//Obter a posição do pixel da partícula de texto Circle.prototype.getTextPixelPosition = function (width,height) { var left = (this.iCanvasW - width)/2; = (this.iCanvasH - altura)/2; var espaço = 4; i=0;i<this.textHeight;i+=espaço){ for(var j=0;j<this.textWidth;j+=espaço){ 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();}//A partícula se move para a posição especificada Circle.prototype.animateToText = function(){ for(var i=0;i<This .actorNumber ;i++){ dinâmica.animate(This.ballActor[i], { x: this.ballActor[i].targetX, y: this.ballActor[i].targetY },{ type: dinâmica.easeIn, duração: 1024, } } setTimeout(function(){ This.ballbackType(); },3000);}//As partículas retornam para o Circule ao longo do caminho original .prototype.ballBackPosition = function(){ for(var i=0;i<This.actorNumber;i++){ var ball = This.ballActor[i]; ); }}// Obter tipo | efeito de animação Circle.prototype.getAnimateType = function() { var selectType = document.getElementById(selectType); var selectDynamics = document.getElementById(selectDynamics); this.backType = selectType.options[selectType.options.selectedIndex].value; //Redefinir círculo de propagação .prototype.ballbackType = function(){ if(this.backType == voltar){ this.ballBackPosition(); }else{ this.ballAutoPosition() } this.ballActor = [];}// Espalhar aleatoriamente Circle.prototype.ballAutoPosition = function(ball){ for(var i= 0 ;i<this.actorNumber;i++){ this.changeStatus(this.ballActor[i]) }}// Alterar o status da bola Circle.prototype.changeStatus = function(ball){ ball.status = 0; if(this.isPlay == true){ this.isPlay = false }}// Gerar aleatoriamente os parâmetros relevantes de cada círculo Circle; .prototype.generalRandomParam = function(){ for(var i=0;i<this.ballNumber;i++){ var ball = {}; Gerar aleatoriamente o raio do círculo // Gerar aleatoriamente o centro do círculo x coordenada ball.x = ramdomNumber(0+ball.size, this.iCanvasW-ball.size); .tamanho);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; 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;// Desenha um círculo Circle.prototype.renderBall = function(ball){ this.ctx .fillStyle = #fff; this.ctx.beginPath(); // Isso deve ser adicionado com this.ctx.arc(ball.x, ball.y, ball.size, 0, 2 * Math.PI); this.ctx.closePath(); // Isso deve ser adicionado com this.ctx.fill();}// Julgamento de colisão de bola 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 } se; (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;// Iniciar animação Circle.prototype.ballAnimate = function(){ var This = this; ; var animateFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || 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] }); })();}//Gerar um número aleatório function ramdomNumber(min, max) { return Math.random() * (max - min) + min;}
Depois de ler o código, acho que foi só um exibicionismo e não te deu vontade de fazer isso, sei que você tem que se convencer com os olhos e a boca. DEMO Online: Exemplo de partículas dinâmicas.
Ninguém é perfeito e o código também não. O código que parece estar funcionando perfeitamente tem mais ou menos falhas. Atualmente, esse efeito só suporta chinês. Quanto ao inglês, tenho que trabalhar mais, não importa o que aconteça, o inglês com certeza vai entrar mais tarde, é só uma questão de tempo. Há também um atributo no código usado para marcar se o texto gerado pode ser executado novamente: this.isPlay, o que ainda é uma pequena falha. A mudança de estado de this.isPlay não muda exatamente no momento em que as partículas retornam. mas muda o estado antecipadamente. Mas este estado não afetará a implementação completa do efeito deste exemplo.
Neste exemplo, a biblioteca dinâmica.js é usada, principalmente para usar algumas funções de movimento nela para tornar o movimento das partículas mais impressionante, só isso.
O texto acima é todo o conteúdo deste artigo. Espero que seja útil para o estudo de todos. Também espero que todos apoiem a Rede VeVb Wulin.