이 글은 Canvas 텍스트의 파티클 효과 구현 코드를 소개하고 모든 분들께 도움이 되기를 바랍니다.
입자를 통해 텍스트를 그리는 것은 흥미롭고 입자의 움직임을 일치시키면 효과가 더욱 멋집니다. 이 문서에서는 캔버스의 입자를 통해 텍스트를 그리는 방법을 소개합니다.
구현원리일반적으로 텍스트를 입자 표시로 변환하는 효과를 만드는 것은 매우 간단합니다. 구현 원리는 두 개의 캔버스를 사용하는 것입니다. 하나는 사용자가 볼 수 없는 A 캔버스이고, 다른 하나는 텍스트를 그리는 데 사용됩니다. 획득한 B 캔버스는 A의 텍스트 데이터를 기반으로 파티클을 생성하는 데 사용됩니다. 직관적인 표현이 그림에 나와 있습니다.
오프스크린 캔버스 만들기HTML은 기본 캔버스에만 배치하면 됩니다.
<!-- HTML 구조--><html><head> ...</head><body> <canvas id=stage></canvas></body></html>
그런 다음 오프스크린 캔버스를 만들고 텍스트를 그립니다.
const WIDTH = window.innerWidth;const HEIGHT = window.innerHeight;const offscreenCanvas = document.createElement('canvas');const offscreenCtx = offscreenCanvas.getContext('2d');offscreenCanvas.width = WIDTH;offscreenCanvas.height = HEIGHT; offscreenCtx.font = '100px PingFang SC';offscreenCtx.textAlign = 'center';offscreenCtx.baseline = 'middle';offscreenCtx.fillText('Hello', WIDTH / 2, HEIGHT / 2);현재 페이지에서는 아무 일도 일어나지 않지만 화면 밖의 캔버스에서는 실제로 상상할 수 있습니다. 그림과 같습니다.
핵심 메소드 getImageData 캔버스의 getImageData 메소드를 사용하면 캔버스의 지정된 영역에 있는 픽셀 데이터를 설명하는 데 사용되는 ImageData 개체를 얻을 수 있습니다. 즉, Hello 텍스트의 각 픽셀의 위치와 색상을 얻을 수 있으며 지정된 위치에 입자를 생성할 수 있습니다. 최종 효과는 입자가 텍스트로 합쳐지는 것입니다.
픽셀 정보를 얻으려면 모든 픽셀의 rgba 값을 배열로 분산시키는 ImageData 개체의 data 속성을 사용해야 합니다. 각 픽셀에는 4개의 rgba 값이 있습니다. 이 배열의 수는 像素点数量* 4 입니다. .
3 * 4 영역을 선택했다고 가정하면 총 12개의 픽셀이 있고 각 픽셀에는 4개의 rgba 값이 있으므로 데이터 배열에는 12 * 4 = 48 요소가 있습니다.
데이터를 인쇄하면 이러한 픽셀의 rgba가 왼쪽에서 오른쪽, 위에서 아래로 배열된 것을 볼 수 있습니다.
물론, 우리가 얻고자 하는 영역에는 텍스트가 포함되어야 하므로 전체 오프스크린 캔버스 영역을 얻어야 합니다.
const imgData = offscreenCtx.getImageData(0, 0, WIDTH, HEIGHT).data;입자 생성
ImageData를 가져온 후 데이터 배열을 순회하면 오프스크린 캔버스의 어떤 점에 색상이 지정되어 있는지(텍스트 중간에 있음), 어떤 점이 색상이 없는지(텍스트에 없음) 확인하고 해당 색상의 픽셀을 배치할 수 있습니다. 위치를 기록한 다음 기본 캔버스에 입자를 생성하면 됩니다.
먼저 입자 클래스를 만듭니다.
클래스 파티클 { 생성자 (옵션 = {}) { const { x = 0, y = 0, color = '#fff', radius = 5} = options; = y; this.color = 색상; } draw (ctx) { ctx.beginPath()(this.x, this.y, this.radius, 0, 2 * Math.PI, false); ctx.fillStyle = ctx.fill();데이터를 탐색하면 투명도를 기반으로 텍스트에 픽셀이 있는지, 즉 rgba의 네 번째 요소가 0이 아닌지 확인할 수 있습니다.
const 입자 = [];const 건너뛰기 = 4;for (var y = 0; y < HEIGHT; y += 건너뛰기) { for (var x = 0; x < WIDTH; x += 건너뛰기) { var opacityIndex = (x + y * WIDTH) * 4 + 3; if (imgData[opacityIndex] > 0) { 입자.push(new 입자({ x, y, 반경: 1, 색상: '#2EA9DF' })) } }} 모든 입자를 저장하기 위해 particles 배열을 사용합니다. 여기에서 skip 기능은 순회 단계 크기입니다. 픽셀 단위로 스캔하면 결국 텍스트를 하나로 묶는 입자가 매우 조밀해집니다. 입자가 더 희박하게 생성됩니다.
마지막으로 메인 캔버스를 생성하고 그립니다.
const canvas = document.querySelector('#stage');canvas.width = WIDTH;canvas.height = HEIGHT;const ctx = canvas.getContext('2d');for (const 입자의 입자) { 입자.draw(ctx );}효과는 다음과 같습니다.
전체 코드는 01-basic-text-to-particles를 참조하세요.
효과 추가구현 원리를 이해한 후 나머지는 실제로 입자에 애니메이션 효과를 추가하는 것입니다. 첫째, 너무 깔끔하게 보이지 않도록 입자에 임의의 변위를 부여할 수 있습니다.
const 입자 = [];const 건너뛰기 = 4;for (var y = 0; y < HEIGHT; y += 건너뛰기) { for (var x = 0; x < WIDTH; x += 건너뛰기) { var opacityIndex = (x + y * WIDTH) * 4 + 3; if (imgData[opacityIndex] > 0) { // 입자를 생성할 때 무작위 변위를 추가합니다. Particle({ x: x + Math.random() * 6 - 3, y: y + Math.random() * 6 - 3, 반경: 1, 색상: '#2EA9DF' }));효과는 다음과 같습니다.
다음과 같이 더 큰 효과를 얻으려는 경우:
이를 구현하는 방법 먼저 입자의 크기를 무작위로 생성해야 합니다. 이를 위해서는 입자를 생성할 때 반경을 무작위로 지정하면 됩니다. 또한 입자 반경을 동적으로 변경하려면 입자의 렌더링 반경과 초기 반경을 구별하고 애니메이션 렌더링에 requestAnimationFrame 사용해야 합니다.
class Particle { 생성자 (옵션 = {}) { const { x = 0, y = 0, color = '#fff', radius = 5} = options; this.radius = radius; radius; // DynamicRadius 속성 추가} draw (ctx) { // ... ctx.arc(this.x, this.y, this.dynamicRadius, 0, 2 * Math.PI, false) // DynamicRadius로 대체 // ... } update () { // TODO }}requestAnimationFrame(function loop() { requestAnimationFrame(loop); ctx.fillStyle = '#fff'; ctx.fillRect(0, 0, WIDTH, HEIGHT ); for (입자의 상수 입자) {particle.update();particle.draw(ctx) }}); 그러면 핵심은 입자의 update 방법을 구현하는 방법에 있습니다. 입자 반경이 1에서 5까지 원활하고 주기적으로 변경되기를 원한다고 가정합니다. 다음과 같은 삼각 함수를 생각하기 쉽습니다.
가로축은 시간과 관련이 있어야 하며 업데이트를 호출할 때마다 변수를 추가할 수 있으며 타임스탬프를 사용하여 간단히 계산할 수도 있습니다. update 방법의 예는 다음과 같습니다.
업데이트 () { this.dynamicRadius = 3 + 2 * Math.sin(new Date() / 1000 % 1000 * this.radius);}전체 코드는 02-text-to-particles-with-size-changing을 참조하세요.
위의 내용은 이 기사의 전체 내용입니다. 모든 분들의 학습에 도움이 되기를 바랍니다. 또한 모든 분들이 VeVb Wulin Network를 지지해 주시길 바랍니다.