최고는 없고 더 나은 것은 없습니다. 제목에서 알 수 있듯이 이 기사에서는 Canvas를 사용하여 얻은 입자 이동 효과만 공유하려고 합니다. 약간의 헤드라인처럼 느껴지지만 다른 관점에서 보면 거의 눈부시다고 볼 수 없습니다. 색상은 눈부심과 관련이 없지만 움직임 효과는 여전히 약간 눈부십니다. 어쨌든 소위 눈부신 효과를 시작해 보겠습니다!
이해가 되지 않으면 코드로 직접 이동하여 코드 주석을 읽어보세요. 당신은 아마도 일반적인 생각을 이해할 것입니다.
HTML 코드
<!DOCTYPE html><html lang=en><head><meta charset=UTF-8><title>캔버스는 눈부신 입자 모션 효과를 구현합니다 - 클라우드 라이브러리 프런트 엔드</title><style>* { margin: 0; : 0;}html,body { 너비: 100%; 높이: 100%;} 캔버스 { 디스플레이: 블록 배경: #000;}body::-webkit-scrollbar{ 디스플레이: 없음;}.operator-box{ 위치: 고정; 상단: 50%; 테두리: 1px 솔리드 #fff; 패딩: 20px 10px; (-50%); 변환: 번역X(-50%);}.back-type,.back-animate{ 여백-오른쪽: 20px;}.flex-box{ 디스플레이: flex; justify-content: center;}#input-text{ line-height: 35px; 높이: rgba(0, 0, 0,0.7); 색상: #fff; 글꼴 크기: 16px; 윤곽선: 없음; 12px; 상자 그림자: 삽입 0 0 12px 1px rgba(0,0,0,0.7);}#input-text::placeholder{ color: #ccc; line-height: 55px;}select{ - 웹킷 모양: 없음; -moz-모양: 없음; 테두리: 없음; 0px 6px; 높이: 35px; 텍스트 정렬: 왼쪽; url(데이터:이미지/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAICAYAAAAAx8TU7AAAAOUlEQ…R4gPgWEIMAiOYBCS4C8ZDAIRBq4gigNkztQEFMi6AuQHESAPMeXiEMiWfpAAAAAAElFTkSuQmCC) 반복 없음 190px 12px; 배경 크기: 5px 8px; 상자 그림자: 삽입 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>스프레드 유형: <select name= id=selectType> <option value=back>반환</option> <option value=auto>Random</option> </select> </div> <div class=back-animate>분산 효과(원점 복귀에 효과적): <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 value=easeIn>dynamics.easeIn</option> 옵션> <option value=linear>dynamics.linear</option> </select> </div> <div class=input-box><input type=text placeholder=한자를 입력하고 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>
HTML 코드는 많지 않으며 단지 몇 가지 운영 요소만 있습니다. 여기서 한 눈에 이해하기 쉽습니다. 너무 많은 말을 낭비할 필요가 없습니다. 이 기사의 주인공인 JavaScript 코드를 살펴보겠습니다. 하지만 코드를 보기 전에 이 효과를 달성한다는 아이디어를 들어보는 것이 좋습니다.
JavaScript 코드에는 this.iCanvas(홈 페이지), this.iCanvasCalculate(텍스트 너비를 계산하는 데 사용됨) 및 this.iCanvasPixel(텍스트를 그리고 텍스트에 해당하는 픽셀의 위치 좌표를 얻는 데 사용됨)의 세 가지 캔버스가 사용됩니다. ) .
this.iCanvasCalculate 및 this.iCanvasPixel은 페이지에 표시될 필요가 없으며 단지 보조 기능일 뿐입니다.
다음은 멋진 JS 구현 코드입니다.
function Circle() { var This = this.init(); this.drawCircles(); this.getUserText(); 화면 가져오기 window.onresize = function(){ This.stateW = document.body.offsetWidth; This.stateH = document.body.offsetHeight; This.iCanvas.width = This.stateW; This.iCanvasH = This.iCanvas.height = This.ctx = This.iCanvas.getContext(2d) }}//Circle.prototype.init = function( ){ //상위 요소 너비 및 높이 this.stateW = document.body.offsetWidth = document.body.offsetHeight; document.createElement(canvas); // 부모 요소와 동일한 너비와 높이를 갖도록 캔버스를 설정합니다. this.iCanvasW = this.iCanvas.width = this.stateW; this.iCanvasH = this.iCanvas.height = this.stateH; // 2D 페인팅 환경 가져오기 this.ctx = this.iCanvas.getContext(2d); // 본문 요소에 삽입 document.body.appendChild(this.iCanvas); this.iCanvasCalculate = document.createElement(canvas); // 계산된 텍스트 너비를 저장하는 데 사용되는 캔버스 this.mCtx = this.iCanvasCalculate.getContext(2d) this.mCtx.font = 128px this.iCanvasPixel = document .createElement; (캔버스); this.iCanvasPixel.setAttribute(style,position:absolute;top:0;left:0;); this.pCtx = null; // 텍스트를 그리는 데 사용되는 캔버스 // 무작위로 생성된 원의 수 this.ballNumber = ramdomNumber(1000 , 2000); // 모든 공의 배열을 저장합니다. this.balls = []; // 애니메이션에서 마지막으로 움직임을 멈춘 공을 저장합니다. this.animte = null; this.imageData = null; this.textWidth = 0; // 생성된 텍스트의 너비를 저장합니다. this.textHeight = 150; // 생성된 텍스트의 높이를 저장합니다. this.inputText = ; this.actionCount = 0; this.ballActor = []; // 텍스트를 생성하는 입자를 저장합니다. this.actorNumber = 0; // 텍스트를 생성하는 입자 수를 저장합니다. // Return this.backDynamics = ; // 애니메이션 효과 this.isPlay = false; // 로고(텍스트 생성 중에는 생성할 수 없음)}// 모든 원 렌더링 Circle.prototype.drawCircles = function () { for(var i=0;i <this.ballNumber ;i++){ this.renderBall(this.balls[0]) }}// 사용자 입력 텍스트 가져오기 Circle.prototype.getUserText = function(){ This = this; // ipu = document.getElementById(input-text)를 가리키도록 저장합니다. ipu.addEventListener(keydown,function(event){ if(event.which === 13){ // Enter 키인 경우 ipu.value = ipu.value.trim(); // 앞뒤 공백 제거 var pat = /[/u4e00-/u9fa5]/ // 중국어 판단 var isChina = pat.test(ipu.value); if(ipu.value.length !=0 && isEnglish){ This.inputText = ipu.value; }else{ Alert(한자를 입력하세요) return; ) { return } This.getAnimateType(); This.getTextPixel(); This.isPlay = true } );}// 텍스트의 너비를 계산합니다. Circle.prototype.calculateTextWidth = function () { this.textWidth = this.mCtx.measureText(this.inputText).width;}// 텍스트 픽셀을 가져옵니다. Circle.prototype.getTextPixel = function () { if(this.pCtx){ this.pCtx.clearRect(0,0,this.textWidth,this.textHeight); this.calculateTextWidth(this.inputText); this.iCanvasPixel.width = this.textWidth = this.textHeight; .pCtx = this.iCanvasPixel.getContext(2d); this.pCtx.font = 128px 마이크로소프트 야헤이; this.pCtx.fillStyle = #FF0000; this.pCtx.textBaseline = botom; this.pCtx.fillText(this.inputText,0,110); 0,0,this.textWidth,this.textHeight).data; this.getTextPixelPosition(this.textWidth,this.textHeight);}//텍스트 입자 픽셀 위치 가져오기 Circle.prototype.getTextPixelPosition = function (width,height) { var left = (this.iCanvasW - width)/2; = (this.iCanvasH - 높이)/2; var space = 4 for(var; 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();}//입자가 지정된 위치로 이동합니다. 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);}//입자가 원래 경로를 따라 원을 그립니다. .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 },{ 유형: 역학[this.backDynamics], 기간: 991, 완료:this.changeStatus(ball) } ); }}// 유형 가져오기|애니메이션 효과 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;}//확산 원 재설정 .prototype.ballbackType = function(){ if(this.backType == back){ this.ballBackPosition(); }else{ this.ballAutoPosition(); } this.ballActor = [];}// 무작위로 분산 Circle.prototype.ballAutoPosition = function(ball){ for(var i= 0 ;i<this.actorNumber;i++){ this.changeStatus(this.ballActor[i]) }}// 공 상태 변경 Circle.prototype.changeStatus = function(ball){ ball.status = 0; if(this.isPlay == true){ this.isPlay = false }}// 각 원의 관련 매개변수를 무작위로 생성합니다. .prototype.generalRandomParam = function(){ for(var i=0;i<this.ballNumber;i++){ var ball = {} = 1; 원 반경 무작위 생성 // 원 중심 x 좌표 무작위 생성 ball.x = ramdomNumber(0+ball.size, this.iCanvasW-ball.size) ball.y = ramdomNumber(0+ball.size, this.iCanvasH-ball . 크기); ball.speedX = ramdomNumber(-1, 1); ball.speedY = ramdomNumber(-1, 1); ball.status = 0; ball.targetY = 0; ball.backX = 0; }}// 원의 위치 변경 Circle.prototype.changeposition() 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; } }}// 원 그리기 Circle.prototype.renderBall = function(ball){ this.ctx . fillStyle = #fff; this.ctx.beginPath(); // this.ctx.arc(ball.x, ball.y, ball.size, 0, 2 * Math.PI); this.ctx.closePath(); // this.ctx.fill()로 추가해야 합니다;}// 공 충돌 판단 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.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; } }}// 애니메이션 시작 Circle.prototype.ballAnimate = function(){ var This = ; var animateFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || 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]); })();}//난수 생성 함수 ramdomNumber(min, max) { return Math.random() * (max - min) + min;}
코드를 읽어보니 그냥 과시용이었던 것 같고, 만들고 싶은 마음이 들지 않았던 것 같아요. 그렇기 때문에 눈으로 확인해야 한다는 걸 압니다. 온라인 데모: 동적 입자의 예.
완벽한 사람은 없고 코드도 마찬가지입니다. 원활하게 실행되는 코드에도 약간의 결함이 있는 것 같습니다. 현재 이 효과는 중국어만 지원합니다. 영어는 더 열심히 해야 하는데, 무슨 일이 있어도 영어는 나중에 꼭 합류하게 될 테니 시간 문제일 뿐입니다. 코드에는 생성된 텍스트를 다시 실행할 수 있는지 여부를 표시하는 데 사용되는 속성이 있습니다: this.isPlay는 아직 약간의 결함이 있습니다. this.isPlay의 상태 변경은 입자가 반환되는 순간 정확하게 변경되지 않습니다. 하지만 상태를 미리 변경합니다. 그러나 이 상태는 이 예제 효과의 완전한 구현에 영향을 미치지 않습니다.
이 예에서는 Dynamics.js 라이브러리가 주로 사용되어 입자가 더욱 인상적으로 움직이도록 하기 위해 일부 모션 기능을 사용합니다. 그게 전부입니다.
위의 내용은 이 기사의 전체 내용입니다. 모든 분들의 학습에 도움이 되기를 바랍니다. 또한 모든 분들이 VeVb Wulin Network를 지지해 주시길 바랍니다.