Hướng dẫn tạo hiệu ứng tuyết rơi với Canvas HTML5

Canvas HTML5

Hello mọi người, mình mới tìm hiểu một chút về canvas HTML5 nên hôm nay mình sẽ hướng dẫn các bạn tạo ra một bầu trời tuyết rơi đầy lãng mạn nhé. 😘

Vậy Canvas HTML5 là gì ?

1. Canvas là gì ?

Canvas là một phần tử của HTML5, cho phép thực hiện lập trình kết xuất đồ họa các đối tượng hai chiều trên trang web. Canvas chiếm một khu vực trong trang web với chiều rộng và chiều cao định trước. Sau đó sử dụng Javascript có thể truy cập vào khu vực này để vẽ thông qua một tập các hàm đồ họa tương tự như các API 2D khác.

2. Hướng dẫn tạo tuyết rơi với canvas và javascript

  • Khởi tạo và resizing canvas

Trước tiên, tạo một thẻ html <canvas /> vào file index.html của bạn

index.html

<!DOCTYPE html>
<html>
    <head>
      <meta charset="UTF-8">
      <title>Canvas HTML5</title>
    </head>
    <body>
        <canvas id="canvas" />
    </body>
</html>

Hãy đặt cho thẻ <canvas> của bạn môt id nhé, và ở đây mình đặt cho nó một id="canvas"

Giờ thì chúng ta sẽ tiến hành khởi tạo canvas trong file javascript, hãy nhớ link script file này vào file index.html của bạn.

index.js

const canvas = document.getElementById('canvas');

const c = canvas.getContext('2d');

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

getContext('2d') là phương thức trả về một Object cung cấp các phương thức và thuộc tính mà chúng ta có thể vẽ trên canvas. Mặc định <canvas> sẽ là một hình chữ nhật, chúng ta set chiều dài, rộng cho nó bằng với chiều dài, rộng của window (tùy thuộc vào bài toán để set kích thước cho nó). Để kích thước của canvas có thể dynamic theo kích thước của window, chúng ta sẽ lắng nghe sự kiện resize của window để set lại kích thước cho canvas.

index.js

window.addEventListener('resize', function() {
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
})
  • Vẽ phần tử trong canvas

Bây giờ sẽ vẽ các phần tử hay các khối shape trong canvas, cụ thể ở demo này chúng ta sẽ vẽ một bông tuyết (hình tròn).

c.beginPath();
c.arc(100, 100, 7, 0, Math.PI * 2);
c.shadowColor = '#fff';
c.shadowBlur = 5;
c.fillStyle = '#fff';
c.fill();
c.closePath();

arc(x, y, radius, 0, 2PI) là phương thức để vẽ một hình tròn.

Trong đó:

  • x, y : là vị trí của hình tròn so với canvas.

  • radius: bán kính của hình tròn.

  • 0, PI *2 : nghĩa là 1 vòng của hình tròn

Để tìm hiểu thêm vẽ các shape khác và các thuộc tích của c các bạn tìm hiểu thêm ở đây nhé:

https://www.w3schools.com/html/html5_canvas.asp

Và đây là kết quả

Các bạn có thể style background cho canvas như demo nhé.

  • Animating phần tử trong canvas

Chúng ta có thể thấy để animate thì vị trí của 'bông tuyết' sẽ thay đổi đồng nghĩa với tọa độ (x, y) của 'bông tuyết' sẽ thay đổi liên tục. Để tiếp tục, mình sẽ xây dựng 'bông tuyết' như một đối tượng với các thuộc tính x ,y, radius, color.

function snow() {
  this.radius = Math.random() * 5;
  this.x = Math.floor(Math.random() * canvas.width);
  this.y = 100;
  this.color = '#FFF';
}

snow.prototype.draw = function() {
  c.beginPath();
  c.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
  c.shadowColor = this.color;
  c.shadowBlur = 5;
  c.fillStyle = this.color;
  c.fill();
  c.closePath();
}

this.x sẽ là random từ 0 đến chiều rộng của canvas.

this.y = - this.radius tạo hiệu ứng 'bông tuyết' luôn luôn rơi từ trên xuống.

Bây giờ mình sẽ thay đổi x, y thì chúng ta sẽ có một 'bông tuyết đang rơi. 😜

function snow() {
  ...
  this.speed = {
      x: Math.random() * 4 - 2,
      y: Math.random() * 3 + 2,
  }
}

snow.prototype.update = function() {
  this.x += this.speed.x;
  this.y += this.speed.y;
  
  if (this.y >= canvas.height)
    this.speed.y = 0;
   
  this.draw();
}

Mình sẽ thêm một thuộc tính speed cho snow thể hiện tốc đô rơi của nó. Để có thể giữ lại các snow của mình lại ở dưới khung canvas, mình thêm điều kiện this.y > canvas.height

Và quan trọng nhất bây giờ là chúng ta cần handle liên tục việc x, y thay đổi. Đừng lo window.requestAnimationFrame sẽ giúp bạn làm điều đó.

Khi muốn thực hiện một vòng lặp thời gian trong JavaScript chúng ta nghĩ ngay đến setInterval(). Tuy nhiên, mục đích của mình là thực hiện animation, để thực hiện một animation mượt mà, chúng ta cần 60 frame/ 1s như thế này

setInterval(function() { // chay animation ở đây }, 1000/60);

Tuy nhiên chúng ta có một cách tốt hơn cách trên, dùng window.requestAnimationFrame(). Để tìm hiểu thêm về nó, bạn có thể tham khảo tại đây:

https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame

Tiếp tục với demo của chúng ta

function animate() {
  c.clearRect(0,0, canvas.width, canvas.height);
  a.update();
  window.requestAnimationFrame(animate);
}

animate();

clearReact giúp chúng ta xóa đi hoạt hình cũ sau khi animate được gọi lại.

Kết quả

Và cuối cùng, một bông tuyết thôi thì chưa phải mùa đông, phải thật nhiều tuyết rơi mới đúng phải không mn 😘

Việc còn lại thật dễ dàng

const arr = [];

function init() {
  arr.push(new snow());
}

function animate() {
  c.clearRect(0,0, canvas.width, canvas.height);
  arr.forEach(function(item) {
    item.update();
  })
  if (arr.length > 1000) {
    arr.splice(0,1);
  }
  init();
  window.requestAnimationFrame(animate);
}

animate();

Kết quả

Trong Canvas sẽ còn những tương tác với phần tử nhưng mình sẽ nới ở bài viết với những demo sau.

3. Kết luận

Trên đây là những hướng dẫn tạo một cảnh tuyết rơi bằng Canvas HTML5, thông qua đó hi vọng sẽ giúp các bạn phần nào hiểu về cách tạo, hoạt động của canvas. Bài viết còn nhiều thiếu sót, mong mọi người góp ý để mình bổ sung hoàn thiện những bài viết sau này hơn. Cảm ơn mọi người đã theo dõi.

4. Tài liệu tham khảo


All Rights Reserved