-
[Canvas] 버튼 Particle 이펙트CSS 2019. 1. 30. 22:46
[Canvas] 버튼 Particle 이펙트
HTML 요소의 자유를 결합하여 웹 페이지의 시각적 기능을 향상시키는 방법에 대해 살펴 보겠습니다. 최신브라우저에만 적용이 가능합니다.
초기 상태
See the Pen DOM to Canvas #1 by Zach Saucier (@Zeaklous) on CodePen.
캔버스 버전
html2canvas라는 매우 편리한 라이브러리가 도움이 됩니다.라이브러리를 로드 한 다음 html2canvas를 호출하면 엘리먼트의 캔버스 버전과 함께 Promise가 반환됩니다.See the Pen DOM to Canvas #2 by Zach Saucier (@Zeaklous) on CodePen.
여기에는 HTML 버전과 캔버스 버전의 버튼이 있습니다.캔버스 버전은 "screenshot"으로 사용하거나 특정 위치의 픽셀 색상과 같은 정보의 소스로 사용할 수 있습니다.캔버스에서 데이터 가져 오기
이렇게하려면 특정 위치에서 픽셀 정보를 가져 오는 새로운 함수를 만들어 보겠습니다.원래의 HTML 요소를 대신 보여주기 때문에 색상 데이터를 가져올 캔버스를 표시 할 필요도 없습니다.12345678910function getColorAtPoint(e) {// Get the coordinate of the clicklet x = e.offsetX;let y = e.offsetY;// Get the color data of the canvas version of our element at that locationlet rgbaColorArr = ctx.getImageData(x, y, 1, 1).data;// Do something with rgbaColorArr}cs See the Pen DOM to Canvas #3 by Zach Saucier (@Zeaklous) on CodePen.
이제 위에 가져온 캔버스 정보를 가지고 입자를 생성합니다.123456789101112131415161718192021222324var particleCanvas, particleCtx;function createParticleCanvas() {// Create our canvasparticleCanvas = document.createElement("canvas");particleCtx = particleCanvas.getContext("2d");// Size our canvasparticleCanvas.width = window.innerWidth;particleCanvas.height = window.innerHeight;// Position out canvasparticleCanvas.style.position = "absolute";particleCanvas.style.top = "0";particleCanvas.style.left = "0";// Make sure it's on top of other elementsparticleCanvas.style.zIndex = "1001";// Make sure other elements under it are clickableparticleCanvas.style.pointerEvents = "none";// Add our canvas to the pagedocument.body.appendChild(particleCanvas);}cs 우리는 또한 버튼의 위와 왼쪽뿐 아니라 오른쪽에서 입자를 생성하기 위해 전역 좌표의 위치인 로컬 좌표에서 색상 데이터를 계속 가져와야합니다.좌표 데이터 가져 오기
123456789101112131415btn.addEventListener("click", e => {// Get our color data like beforelet localX = e.offsetX;let localY = e.offsetY;let rgbaColorArr = ctx.getImageData(localX, localY, 1, 1).data;// Get the button's positioning in terms of the windowlet bcr = btn.getBoundingClientRect();let globalX = bcr.left + localX;let globalY = bcr.top + localY;// Create a particle using the color we obtained at the window location// that we calculatedcreateParticleAtPoint(globalX, globalY, rgbaColorArr);});cs 파티클 프로토 타입 만들기
1234567891011121314151617181920212223242526272829303132333435363738/* An "exploding" particle effect that uses circles */var ExplodingParticle = function() {// Set how long we want our particle to animate forthis.animationDuration = 1000; // in ms// Set the speed for our particlethis.speed = {x: -5 + Math.random() * 10,y: -5 + Math.random() * 10};// Size our particlethis.radius = 5 + Math.random() * 5;// Set a max time to live for our particlethis.life = 30 + Math.random() * 10;this.remainingLife = this.life;// This function will be called by our animation logic later onthis.draw = ctx => {let p = this;if(this.remainingLife > 0 && this.radius > 0) {// Draw a circle at the current locationctx.beginPath();ctx.arc(p.startX, p.startY, p.radius, 0, Math.PI * 2);ctx.fillStyle = "rgba(" + this.rgbArray[0] + ',' + this.rgbArray[1] + ',' + this.rgbArray[2] + ", 1)";ctx.fill();// Update the particle's location and lifep.remainingLife--;p.radius -= 0.25;p.startX += p.speed.x;p.startY += p.speed.y;}}}cs 입자 팩토리 만들기
또한 좌표와 색상 정보를 기반으로 입자를 생성하는 함수가 필요합니다. 생성 된 입자의 배열에 추가해야합니다.12345678910var particles = [];function createParticleAtPoint(x, y, colorData) {let particle = new ExplodingParticle();particle.rgbArray = colorData;particle.startX = x;particle.startY = y;particle.startTime = Date.now();particles.push(particle);}cs 애니메이션 논리 추가
또한 생성된 모든 입자에 애니메이션을 적용하는 방법이 필요합니다.12345678910111213141516171819202122232425function update() {// Clear out the old particlesif(typeof particleCtx !== "undefined") {particleCtx.clearRect(0, 0, window.innerWidth, window.innerHeight);}// Draw all of our particles in their new locationfor(let i = 0; i < particles.length; i++) {particles[i].draw(particleCtx);// Simple way to clean up if the last particle is done animatingif(i === particles.length - 1) {let percent = (Date.now() - particles[i].startTime) / particles[i].animationDuration[i];if(percent > 1) {particles = [];}}}// Animate performantlywindow.requestAnimationFrame(update);}window.requestAnimationFrame(update);cs HTML 요소를 기반으로 입자를 만들 수 있습니다!See the Pen DOM to Canvas #4 by Zach Saucier (@Zeaklous) on CodePen.
한 픽셀 대신 클릭하여 전체 버튼을 "폭발"시키려면 클릭 기능 만 수정하면됩니다.12345678910111213141516171819202122232425262728let reductionFactor = 17;btn.addEventListener("click", e => {// Get the color data for our buttonlet width = btn.offsetWidth;let height = btn.offsetHeightlet colorData = ctx.getImageData(0, 0, width, height).data;// Keep track of how many times we've iterated (in order to reduce// the total number of particles create)let count = 0;// Go through every location of our button and create a particlefor(let localX = 0; localX < width; localX++) {for(let localY = 0; localY < height; localY++) {if(count % reductionFactor === 0) {let index = (localY * width + localX) * 4;let rgbaColorArr = colorData.slice(index, index + 4);let bcr = btn.getBoundingClientRect();let globalX = bcr.left + localX;let globalY = bcr.top + localY;createParticleAtPoint(globalX, globalY, rgbaColorArr);}count++;}}});cs See the Pen DOM to Canvas #5 by Zach Saucier (@Zeaklous) on CodePen.
웹은 이제 더 창조적인 자유를 행사하기 위해 캔버스와 같은 추가 기능을 사용할 수 있다는 것을 알게 되었습니다.
가장자리 감지 기능을 사용하여 요소가 컨테이너 경계 외부에 있는지 (예 :보기에서 숨겨져 있는지) 알려주고 요소가 경계 외부로 나가면 입자를 생성하여 훨씬 더 창의적으로 처리 할 수 있습니다.출처 : https://css-tricks.com/adding-particle-effects-to-dom-elements-with-canvas/'CSS' 카테고리의 다른 글
Bootstrap5 새소식(큰 변화 4가지) (6) 2019.12.22 [CSS] Rethinking CSS (0) 2019.01.31 [Reflow] Reflow 최소화 (0) 2019.01.29 Will-Change (0) 2019.01.22 잘 알려지지 않은 CSS 팁 (1) 2019.01.01