canvas2d

canvas2d

常用 API

Canvas 2D 是 HTML5 提供的一种绘图 API,用于在网页中创建和操作 2D 图形。它通过 <canvas> 元素提供一个绘图区域,开发者可以使用 JavaScript 来绘制图形、文本、图像等内容。以下是 Canvas 2D 的一些常用 API 和功能,以及示例代码。

1. 初始化 Canvas

首先需要在 HTML 中创建一个 <canvas> 元素,并通过 JavaScript 获取其上下文。

1
<canvas id="myCanvas" width="500" height="500"></canvas>
1
2
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d'); // 获取 2D 绘图上下文

2. 绘制基本图形

绘制矩形

  • 填充矩形
    1
    2
    ctx.fillStyle = 'red'; // 设置填充颜色
    ctx.fillRect(10, 10, 100, 100); // (x, y, width, height)
  • 绘制矩形边框
    1
    2
    ctx.strokeStyle = 'blue'; // 设置边框颜色
    ctx.strokeRect(130, 10, 100, 100); // (x, y, width, height)

绘制圆形

  • 填充圆形
    1
    2
    3
    4
    ctx.beginPath(); // 开始路径
    ctx.fillStyle = 'green';
    ctx.arc(250, 60, 50, 0, Math.PI * 2); // (x, y, radius, startAngle, endAngle)
    ctx.fill(); // 填充路径
  • 绘制圆形边框
    1
    2
    3
    4
    ctx.beginPath();
    ctx.strokeStyle = 'purple';
    ctx.arc(350, 60, 50, 0, Math.PI * 2);
    ctx.stroke(); // 描边路径

绘制线条

1
2
3
4
5
ctx.beginPath();
ctx.moveTo(10, 200); // 移动到起点
ctx.lineTo(150, 200); // 绘制到终点
ctx.strokeStyle = 'orange';
ctx.stroke();

绘制贝塞尔曲线

  • 二次贝塞尔曲线
    1
    2
    3
    4
    5
    ctx.beginPath();
    ctx.moveTo(10, 300);
    ctx.quadraticCurveTo(100, 150, 200, 300); // (cpX, cpY, endX, endY)
    ctx.strokeStyle = 'black';
    ctx.stroke();
  • 三次贝塞尔曲线
    1
    2
    3
    4
    5
    ctx.beginPath();
    ctx.moveTo(250, 300);
    ctx.bezierCurveTo(300, 100, 400, 100, 450, 300); // (cp1X, cp1Y, cp2X, cp2Y, endX, endY)
    ctx.strokeStyle = 'brown';
    ctx.stroke();

3. 绘制文本

绘制文本

1
2
3
ctx.font = '20px Arial'; // 设置字体样式
ctx.fillStyle = 'red';
ctx.fillText('Hello Canvas!', 10, 400); // (text, x, y)

绘制文本边框

1
2
3
ctx.font = '20px Arial';
ctx.strokeStyle = 'blue';
ctx.strokeText('Hello Canvas!', 10, 450);

4. 图像绘制

将图片绘制到 Canvas 上。

1
2
3
4
5
const img = new Image(); // 创建图片对象
img.src = 'path/to/image.jpg'; // 设置图片路径
img.onload = function() {
ctx.drawImage(img, 10, 500, 100, 100); // (image, x, y, width, height)
};

5. 设置样式和颜色

填充样式

1
ctx.fillStyle = 'rgba(255, 0, 0, 0.5)'; // RGBA 颜色

边框样式

1
ctx.strokeStyle = '#00ff00'; // 十六进制颜色

线宽

1
ctx.lineWidth = 5; // 设置线条宽度

线帽和线连接

1
2
ctx.lineCap = 'round'; // 线帽类型:butt、round、square
ctx.lineJoin = 'bevel'; // 线连接类型:bevel、round、miter

6. 路径操作

保存和恢复路径状态

1
2
3
4
ctx.save(); // 保存当前状态
ctx.fillStyle = 'blue';
ctx.fillRect(10, 10, 100, 100);
ctx.restore(); // 恢复之前的状态

裁剪路径

1
2
3
4
5
ctx.beginPath();
ctx.rect(10, 10, 100, 100); // 定义裁剪区域
ctx.clip(); // 裁剪
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 200, 200); // 只在裁剪区域内绘制

7. 变换操作

平移

1
2
ctx.translate(100, 100); // (x, y)
ctx.fillRect(0, 0, 100, 100); // 相对于平移后的坐标

旋转

1
2
3
ctx.translate(200, 200); // 移动到旋转中心
ctx.rotate(Math.PI / 4); // 旋转角度(弧度)
ctx.fillRect(-50, -50, 100, 100); // 绘制矩形

缩放

1
2
ctx.scale(2, 2); // (xScale, yScale)
ctx.fillRect(10, 10, 50, 50); // 缩放后的绘制

8. 图像数据操作

获取图像数据

1
2
const imageData = ctx.getImageData(10, 10, 100, 100); // (x, y, width, height)
console.log(imageData.data); // 获取像素数据

修改图像数据

1
2
3
4
5
const imageData = ctx.getImageData(10, 10, 100, 100);
for (let i = 0; i < imageData.data.length; i += 4) {
imageData.data[i] = 255; // 修改红色通道
}
ctx.putImageData(imageData, 10, 10); // 将修改后的数据绘制回 Canvas

9. 清除画布

1
ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除指定区域

10. 绘制复杂图形

绘制多边形

1
2
3
4
5
6
7
ctx.beginPath();
ctx.moveTo(100, 100);
ctx.lineTo(200, 100);
ctx.lineTo(150, 200);
ctx.closePath(); // 闭合路径
ctx.fillStyle = 'yellow';
ctx.fill();

绘制星形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function drawStar(ctx, x, y, spikes, outerRadius, innerRadius) {
let rot = Math.PI / 2 * 3;
let x0 = x;
let y0 = y;
let angle = Math.PI / spikes;
ctx.beginPath();
ctx.moveTo(x0, y0 - outerRadius);
for (let i = 0; i < spikes; i++) {
x0 = x + Math.cos(rot) * outerRadius;
y0 = y + Math.sin(rot) * outerRadius;
ctx.lineTo(x0, y0);
rot += angle;
x0 = x + Math.cos(rot) * innerRadius;
y0 = y + Math.sin(rot) * innerRadius;
ctx.lineTo(x0, y0);
rot += angle;
}
ctx.lineTo(x, y - outerRadius);
ctx.closePath();
ctx.fill();
}
drawStar(ctx, 300, 300, 5, 50, 20);

11. 事件交互

鼠标事件

1
2
3
4
5
6
7
8
canvas.addEventListener('click', function(event) {
const rect = canvas.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
ctx.beginPath();
ctx.arc(x, y, 10, 0, Math.PI * 2);
ctx.fill();
});

12. 动画

简单的动画

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