This programming guide is only available in Vietnamese. Switch to Vietnamese to read the full article.

Bài đầu tiên trong series Canvas sẽ giúp bạn hiểu cách hoạt động của HTML5 Canvas API — từ việc tạo canvas element, lấy rendering context, đến vẽ các hình cơ bản với đầy đủ màu sắc, gradient và pattern.

1. Canvas Element & Context

HTML5 Canvas là một element cho phép vẽ đồ họa 2D (và 3D với WebGL) trực tiếp trên trình duyệt bằng JavaScript. Khác với SVG (vector-based, DOM elements), Canvas là bitmap-based — bạn vẽ pixel trực tiếp lên một bề mặt raster.

canvas_setup.js
// Tạo canvas trong HTML: <canvas id="myCanvas" width="600" height="400"></canvas>
// QUAN TRỌNG: Set width/height qua attribute, KHÔNG qua CSS
// CSS chỉ scale hiển thị, attribute mới set resolution thực

const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d'); // CanvasRenderingContext2D

// Kiểm tra support
if (!canvas.getContext) {
  console.log('Canvas không được hỗ trợ');
}

// Default size nếu không set: 300x150
console.log(canvas.width, canvas.height); // 600 400

// Clear toàn bộ canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);

2. Hệ tọa độ Canvas

Canvas sử dụng hệ tọa độ với gốc (0,0) ở góc trên-trái. Trục x tăng sang phải, trục y tăng xuống dưới (ngược với hệ tọa độ toán học thông thường).

coordinate_system.js
// Hệ tọa độ Canvas:
// (0,0) ──────────► x+
//   │
//   │
//   │
//   ▼
//   y+

// Vẽ grid minh họa hệ tọa độ
function drawGrid(ctx, width, height, step) {
  ctx.strokeStyle = '#333';
  ctx.lineWidth = 0.5;

  for (let x = 0; x <= width; x += step) {
    ctx.beginPath();
    ctx.moveTo(x, 0);
    ctx.lineTo(x, height);
    ctx.stroke();
  }
  for (let y = 0; y <= height; y += step) {
    ctx.beginPath();
    ctx.moveTo(0, y);
    ctx.lineTo(width, y);
    ctx.stroke();
  }
}

drawGrid(ctx, 600, 400, 50);

// Đánh dấu một số điểm
ctx.fillStyle = '#e11d48';
ctx.font = '12px monospace';
ctx.fillText('(0,0)', 5, 15);
ctx.fillText('(300,200)', 305, 215);
ctx.fillText('(600,400)', 505, 395);

3. Vẽ Shapes cơ bản

Canvas cung cấp các phương thức vẽ hình chữ nhật trực tiếp và hệ thống path để vẽ các hình phức tạp hơn. Hãy thử nghiệm trực tiếp với demo bên dưới — thay đổi loại hình, kích thước, tốc độ xoay và quan sát Canvas vẽ lại theo thời gian thực:

🎨 Demo tương tác: Shapes Playground
basic_shapes.js
// === RECTANGLES (hình chữ nhật) ===
ctx.fillStyle = '#3b82f6';
ctx.fillRect(20, 20, 150, 100);    // filled rectangle

ctx.strokeStyle = '#e11d48';
ctx.lineWidth = 3;
ctx.strokeRect(200, 20, 150, 100); // outlined rectangle

ctx.fillRect(380, 20, 150, 100);
ctx.clearRect(400, 40, 110, 60);   // xóa một vùng (transparent)

// === PATHS (đường dẫn) ===
// Vẽ tam giác
ctx.beginPath();
ctx.moveTo(100, 160);    // di chuyển đến điểm bắt đầu
ctx.lineTo(200, 280);    // vẽ đường đến điểm tiếp theo
ctx.lineTo(0, 280);      // vẽ đường tiếp
ctx.closePath();          // nối điểm cuối với điểm đầu
ctx.fillStyle = '#22c55e';
ctx.fill();
ctx.strokeStyle = '#166534';
ctx.lineWidth = 2;
ctx.stroke();

// === CIRCLES & ARCS (hình tròn & cung tròn) ===
// arc(x, y, radius, startAngle, endAngle, counterClockwise)
ctx.beginPath();
ctx.arc(350, 220, 60, 0, Math.PI * 2); // full circle
ctx.fillStyle = '#f59e0b';
ctx.fill();

// Nửa hình tròn
ctx.beginPath();
ctx.arc(500, 220, 60, 0, Math.PI);     // half circle
ctx.fillStyle = '#8b5cf6';
ctx.fill();

// === CURVES (đường cong) ===
// Quadratic Bezier: quadraticCurveTo(cpx, cpy, x, y)
ctx.beginPath();
ctx.moveTo(20, 350);
ctx.quadraticCurveTo(150, 280, 280, 350);
ctx.strokeStyle = '#06b6d4';
ctx.lineWidth = 3;
ctx.stroke();

// Cubic Bezier: bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
ctx.beginPath();
ctx.moveTo(320, 350);
ctx.bezierCurveTo(370, 280, 500, 380, 580, 320);
ctx.strokeStyle = '#ec4899';
ctx.lineWidth = 3;
ctx.stroke();

4. Colors, Gradients & Patterns

Canvas hỗ trợ nhiều cách tô màu: màu đơn sắc, gradient (tuyến tính/hướng tâm) và pattern từ ảnh.

colors_gradients.js
// === COLORS ===
ctx.fillStyle = 'red';              // tên màu
ctx.fillStyle = '#e11d48';          // hex
ctx.fillStyle = 'rgb(225, 29, 72)'; // rgb
ctx.fillStyle = 'rgba(225, 29, 72, 0.5)'; // rgba (có alpha)

// === LINEAR GRADIENT ===
const linearGrad = ctx.createLinearGradient(0, 0, 300, 0); // x0,y0 → x1,y1
linearGrad.addColorStop(0, '#e11d48');
linearGrad.addColorStop(0.5, '#f59e0b');
linearGrad.addColorStop(1, '#22c55e');
ctx.fillStyle = linearGrad;
ctx.fillRect(20, 20, 300, 80);

// === RADIAL GRADIENT ===
const radialGrad = ctx.createRadialGradient(200, 200, 20, 200, 200, 100);
radialGrad.addColorStop(0, '#fff');
radialGrad.addColorStop(1, '#3b82f6');
ctx.fillStyle = radialGrad;
ctx.beginPath();
ctx.arc(200, 200, 100, 0, Math.PI * 2);
ctx.fill();

// === LINE STYLES ===
ctx.lineWidth = 5;
ctx.lineCap = 'round';   // 'butt' | 'round' | 'square'
ctx.lineJoin = 'round';  // 'miter' | 'round' | 'bevel'
ctx.globalAlpha = 0.7;   // transparency cho MỌI drawing tiếp theo

// === PATTERN (từ image) ===
const img = new Image();
img.onload = () => {
  const pattern = ctx.createPattern(img, 'repeat'); // 'repeat'|'repeat-x'|'repeat-y'|'no-repeat'
  ctx.fillStyle = pattern;
  ctx.fillRect(0, 300, 600, 100);
};
img.src = 'texture.png';

5. Thực hành: Vẽ cảnh đơn giản

Kết hợp tất cả kiến thức trên để vẽ một cảnh đơn giản gồm nhà, cây và mặt trời.

simple_scene.js
const canvas = document.getElementById('sceneCanvas');
const ctx = canvas.getContext('2d');

// Bầu trời (gradient)
const skyGrad = ctx.createLinearGradient(0, 0, 0, 300);
skyGrad.addColorStop(0, '#1e3a5f');
skyGrad.addColorStop(1, '#87ceeb');
ctx.fillStyle = skyGrad;
ctx.fillRect(0, 0, 600, 300);

// Mặt đất
ctx.fillStyle = '#22c55e';
ctx.fillRect(0, 300, 600, 100);

// Mặt trời
const sunGrad = ctx.createRadialGradient(500, 80, 10, 500, 80, 50);
sunGrad.addColorStop(0, '#fbbf24');
sunGrad.addColorStop(1, '#f59e0b');
ctx.fillStyle = sunGrad;
ctx.beginPath();
ctx.arc(500, 80, 50, 0, Math.PI * 2);
ctx.fill();

// Nhà — thân
ctx.fillStyle = '#dc2626';
ctx.fillRect(100, 220, 150, 120);

// Nhà — mái (tam giác)
ctx.beginPath();
ctx.moveTo(80, 220);
ctx.lineTo(175, 150);
ctx.lineTo(270, 220);
ctx.closePath();
ctx.fillStyle = '#7f1d1d';
ctx.fill();

// Nhà — cửa
ctx.fillStyle = '#92400e';
ctx.fillRect(155, 280, 40, 60);

// Nhà — cửa sổ
ctx.fillStyle = '#fef08a';
ctx.fillRect(120, 245, 30, 25);
ctx.fillRect(200, 245, 30, 25);

// Cây — thân
ctx.fillStyle = '#92400e';
ctx.fillRect(400, 240, 20, 100);

// Cây — tán lá
ctx.fillStyle = '#16a34a';
ctx.beginPath();
ctx.arc(410, 210, 50, 0, Math.PI * 2);
ctx.fill();
ctx.beginPath();
ctx.arc(380, 230, 35, 0, Math.PI * 2);
ctx.fill();
ctx.beginPath();
ctx.arc(440, 230, 35, 0, Math.PI * 2);
ctx.fill();

6. Câu hỏi trắc nghiệm ôn tập

Trắc nghiệm 1: Canvas vs SVG

Canvas vẽ đồ họa theo cách nào?

Trắc nghiệm 2: Hệ tọa độ

Trong hệ tọa độ Canvas, trục y hướng về đâu?

Trắc nghiệm 3: clearRect

Phương thức nào dùng để xóa (clear) một vùng trên canvas?

Tải file code thực hành minh họa bài học

File script tổng hợp các ví dụ về Canvas setup, shapes, colors và gradients:

Tải về canvas_basics.js

Related Articles

Bài viết liên quan trong series

Lesson 2: Text Rendering & Image Drawing on Canvas Bài 2: Text Rendering & Image Drawing trên Canvas Back to Canvas Series Overview Quay lại Lộ trình Canvas Series