Text biến thành Particle khi hover / click bằng HTML5 Canvas

Text Particle Effect là kiểu hiệu ứng mà chữ không chỉ animate đơn thuần, mà có thể “vỡ ra”, tan thành hạt rồi quay trở lại hình dạng ban đầu. Đây là dạng hiệu ứng rất dễ gây “wow”, thường thấy ở landing page sản phẩm, trang giới thiệu hoặc demo kỹ thuật front-end.

Text biến thành Particle khi hover / click bằng HTML5 Canvas

Vấn đề là nhiều bản ngoài kia làm quá tay: particle quá nhiều, canvas nặng, CPU lên cao, nhìn thì vui nhưng không dùng được trong sản phẩm thật.

Bài này làm lại theo hướng khác: particle gọn, logic rõ ràng, chỉ dùng canvas cho đúng mục đích, hover hoặc click là thấy hiệu ứng ngay.

Không thư viện. Không shader. Không màu mè dư thừa.

Tư duy đúng khi làm Text Particle

Bản chất của hiệu ứng này gồm 2 bước:

  • Vẽ chữ lên canvas
  • Lấy dữ liệu pixel để tạo particle

Particle không cần nhiều. Quan trọng là:

  • Vị trí chính xác
  • Chuyển động mượt
  • Có trạng thái quay về

Nếu làm đúng, canvas sẽ chỉ vẽ lại những gì cần thiết.

HTML: Một canvas duy nhất

<canvas id="particleText" width="600" height="200"></canvas>

Không cần thêm div hay layer phụ.

JavaScript: Vẽ chữ và tạo particle

const canvas = document.getElementById('particleText');
const ctx = canvas.getContext('2d');

const text = 'INIT HTML';
const particles = [];
const gap = 4;

ctx.fillStyle = '#fff';
ctx.font = 'bold 64px sans-serif';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(text, canvas.width / 2, canvas.height / 2);

const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
ctx.clearRect(0, 0, canvas.width, canvas.height);

for (let y = 0; y < canvas.height; y += gap) {
  for (let x = 0; x < canvas.width; x += gap) {
    const index = (y * canvas.width + x) * 4;
    if (imageData.data[index + 3] > 128) {
      particles.push({
        x,
        y,
        baseX: x,
        baseY: y,
        vx: 0,
        vy: 0
      });
    }
  }
}

Mỗi particle lưu vị trí gốc để có thể quay về hình chữ ban đầu.

Vẽ và animate particle

function animate() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  particles.forEach(p => {
    p.vx *= 0.9;
    p.vy *= 0.9;
    p.x += p.vx;
    p.y += p.vy;

    const dx = p.baseX - p.x;
    const dy = p.baseY - p.y;
    p.x += dx * 0.05;
    p.y += dy * 0.05;

    ctx.fillStyle = '#fff';
    ctx.fillRect(p.x, p.y, 2, 2);
  });

  requestAnimationFrame(animate);
}

animate();

Particle luôn có lực kéo nhẹ về vị trí ban đầu, nên chữ tự động “liền lại”.

Tương tác hover / click

canvas.addEventListener('mousemove', e => {
  const rect = canvas.getBoundingClientRect();
  const mx = e.clientX - rect.left;
  const my = e.clientY - rect.top;

  particles.forEach(p => {
    const dx = p.x - mx;
    const dy = p.y - my;
    const dist = Math.sqrt(dx * dx + dy * dy);

    if (dist < 60) {
      p.vx += dx * 0.05;
      p.vy += dy * 0.05;
    }
  });
});

canvas.addEventListener('click', () => {
  particles.forEach(p => {
    p.vx += (Math.random() - 0.5) * 20;
    p.vy += (Math.random() - 0.5) * 20;
  });
});

Hover làm particle đẩy ra nhẹ. Click làm chữ “vỡ” mạnh hơn.

Vì sao hiệu ứng này chạy mượt

  • Particle số lượng vừa đủ
  • Dùng requestAnimationFrame
  • Không tạo object mới trong loop
  • Canvas chỉ vẽ pixel đơn giản

Canvas được dùng đúng chỗ, không lạm dụng.

Điều chỉnh cho dự án thật

  • Giảm kích thước chữ trên mobile
  • Tăng gap để giảm particle
  • Chỉ bật hover, tắt click nếu không cần

Hiệu ứng này nên dùng như điểm nhấn, không nên lặp lại nhiều lần trên cùng trang.

Lưu ý quan trọng

  • Không dùng quá nhiều canvas cùng lúc
  • Không đặt animation ở background liên tục
  • Nên dừng animation khi canvas ra khỏi viewport

Kết luận

Text Particle Effect nhìn thì “ảo”, nhưng bản chất chỉ là xử lý pixel một cách có kiểm soát. Khi particle ít, chuyển động có lực kéo và canvas được dùng đúng vai trò, hiệu ứng sẽ vừa wow vừa đủ nhẹ để dùng trong sản phẩm thật.

Làm cho vui thì dễ. Làm để dùng lâu dài mới khó.

Bình luận


  • Không có bình luận.

Init Toolbox

Nhấn Ctrl + \ trên máy tính, hoặc vuốt sang trái ở bất kỳ đâu trên mobile.

Đăng nhập





Đang tải...