HTML Canvas

<canvas> 是一个像素级的绘图区域,通过 JavaScript 可以在上面绘制图形、动画、图表、游戏画面。

创建画布

html
<canvas id="myCanvas" width="400" height="300">
  您的浏览器不支持 Canvas。
</canvas>
javascript
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');

务必用 HTML 属性(或 JavaScript)设置 widthheight。用 CSS 缩放 canvas 会导致内容模糊——CSS 改变的是元素的显示尺寸,而 canvas 的绘制分辨率不会跟着变。

绘制矩形

javascript
const ctx = canvas.getContext('2d');

// 填充矩形
ctx.fillStyle = '#2563eb';
ctx.fillRect(50, 50, 200, 100);

// 描边矩形
ctx.strokeStyle = '#1e40af';
ctx.lineWidth = 3;
ctx.strokeRect(50, 50, 200, 100);

// 清除矩形区域
ctx.clearRect(60, 60, 50, 50);

绘制路径

javascript
const ctx = canvas.getContext('2d');

// 开始路径
ctx.beginPath();
ctx.moveTo(100, 50);    // 移动到起点
ctx.lineTo(200, 150);   // 画线到
ctx.lineTo(100, 150);   // 再画线
ctx.closePath();        // 闭合路径(回到起点)
ctx.fillStyle = '#ef4444';
ctx.fill();

// 绘制圆形
ctx.beginPath();
ctx.arc(300, 100, 40, 0, Math.PI * 2);
ctx.fillStyle = '#22c55e';
ctx.fill();
ctx.stroke();

绘制文字

javascript
ctx.font = '30px system-ui, sans-serif';
ctx.fillStyle = '#1e293b';
ctx.fillText('Hello Canvas!', 50, 250);

ctx.font = 'bold 20px system-ui';
ctx.strokeStyle = '#2563eb';
ctx.strokeText('描边文字', 50, 280);

绘制图片

javascript
const img = new Image();
img.onload = () => {
  ctx.drawImage(img, 0, 0);                    // 原尺寸
  ctx.drawImage(img, 0, 0, 100, 100);          // 缩放到 100×100
  // 裁剪:从原图(20,20)处取(50,50)区域,绘制到canvas(200,200)处尺寸(80,80)
  ctx.drawImage(img, 20, 20, 50, 50, 200, 200, 80, 80);
};
img.src = 'photo.jpg';

颜色与渐变

javascript
// 线性渐变
const gradient = ctx.createLinearGradient(0, 0, 200, 0);
gradient.addColorStop(0, '#2563eb');
gradient.addColorStop(1, '#22c55e');
ctx.fillStyle = gradient;
ctx.fillRect(10, 10, 200, 100);

// 径向渐变
const radial = ctx.createRadialGradient(150, 100, 10, 150, 100, 80);
radial.addColorStop(0, 'white');
radial.addColorStop(1, '#2563eb');
ctx.fillStyle = radial;
ctx.fillRect(50, 50, 200, 100);

动画基础

Canvas 动画的核心是不断重绘——清空画布 → 更新状态 → 重新绘制:

javascript
let x = 0;

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

  ctx.fillStyle = '#2563eb';
  ctx.fillRect(x, 100, 50, 50);

  x += 2;  // 更新位置
  if (x > canvas.width) x = -50;

  requestAnimationFrame(animate);
}

animate();

requestAnimationFrame() 是 Canvas 动画的核心。它告诉浏览器”在下次重绘前执行回调”,让浏览器自行优化帧率(通常 60fps),比 setInterval 更流畅、更省电。

一个完整的示例:绘制笑脸

html
<canvas id="smileCanvas" width="300" height="300"></canvas>
<script>
  const c = document.getElementById('smileCanvas');
  const ctx = c.getContext('2d');

  // 脸
  ctx.beginPath();
  ctx.arc(150, 150, 100, 0, Math.PI * 2);
  ctx.fillStyle = '#fde047';
  ctx.fill();
  ctx.stroke();

  // 左眼
  ctx.beginPath();
  ctx.arc(110, 120, 12, 0, Math.PI * 2);
  ctx.fillStyle = '#1e293b';
  ctx.fill();

  // 右眼
  ctx.beginPath();
  ctx.arc(190, 120, 12, 0, Math.PI * 2);
  ctx.fill();

  // 嘴巴
  ctx.beginPath();
  ctx.arc(150, 160, 50, 0.1 * Math.PI, 0.9 * Math.PI);
  ctx.lineWidth = 4;
  ctx.stroke();
</script>