1. 什么是 <canvas>?
<canvas> 是 HTML5 引入的一个绘图容器 ,它本身只是一个矩形的画布区域,本身不具备绘图能力。所有的图形绘制、动画、图像处理都需要通过 JavaScript 来完成。
它常用于:
- 动态图表与数据可视化
- 游戏开发(2D 渲染)
- 图像滤镜与像素级操作
- 签名板、绘图工具
- 实时视频/图像处理
2. 基本用法
2.1 在 HTML 中定义画布
html
<canvas id="myCanvas" width="400" height="300">
您的浏览器不支持 Canvas,请升级浏览器。
</canvas>
id:便于 JavaScript 获取元素。width/height:画布的实际像素尺寸(不是 CSS 样式尺寸)。- 标签内部的内容(如"您的浏览器不支持...")会在浏览器不支持 Canvas 时显示。
⚠️ 注意 :不要用 CSS 直接设置
width和height,否则会拉伸画布内容。CSS 尺寸只控制显示大小,而width/height属性控制绘图分辨率。
3. 通过 JavaScript 绘制
3.1 获取绘图上下文
javascript
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d'); // 2D 绘图上下文
getContext('2d') 返回一个包含所有绘图方法的对象。
3.2 绘制基础图形
矩形
javascript
// 填充矩形
ctx.fillStyle = '#3498db';
ctx.fillRect(20, 20, 150, 100);
// 描边矩形
ctx.strokeStyle = '#e74c3c';
ctx.lineWidth = 4;
ctx.strokeRect(200, 50, 120, 80);
// 清除矩形区域
ctx.clearRect(50, 50, 80, 60);
路径绘制(圆形、三角形等)
javascript
// 绘制圆形
ctx.beginPath();
ctx.arc(100, 200, 40, 0, Math.PI * 2);
ctx.fillStyle = '#2ecc71';
ctx.fill();
ctx.strokeStyle = '#27ae60';
ctx.stroke();
// 绘制三角形
ctx.beginPath();
ctx.moveTo(250, 180);
ctx.lineTo(300, 250);
ctx.lineTo(200, 250);
ctx.closePath();
ctx.fillStyle = '#f1c40f';
ctx.fill();
3.3 样式与颜色
| 属性 | 说明 |
|---|---|
fillStyle |
填充颜色 / 渐变 / 图案 |
strokeStyle |
描边颜色 |
lineWidth |
线条宽度(像素) |
globalAlpha |
全局透明度(0~1) |
javascript
ctx.fillStyle = 'rgba(255, 99, 132, 0.7)';
ctx.strokeStyle = '#2c3e50';
ctx.lineWidth = 6;
3.4 绘制文本
javascript
ctx.font = 'bold 28px "Segoe UI", sans-serif';
ctx.fillStyle = '#2c3e50';
ctx.fillText('Hello Canvas', 30, 100);
ctx.strokeStyle = '#e74c3c';
ctx.lineWidth = 2;
ctx.strokeText('描边文字', 30, 160);
3.5 绘制图像
javascript
const img = new Image();
img.src = 'image.png';
img.onload = () => {
ctx.drawImage(img, 50, 50, 200, 150); // 缩放绘制
};
4. 高级特性
4.1 渐变
javascript
// 线性渐变
const gradient = ctx.createLinearGradient(0, 0, 200, 0);
gradient.addColorStop(0, '#ff6b6b');
gradient.addColorStop(1, '#feca57');
ctx.fillStyle = gradient;
ctx.fillRect(10, 10, 300, 80);
// 径向渐变
const radGrad = ctx.createRadialGradient(150, 150, 20, 150, 150, 80);
radGrad.addColorStop(0, '#a29bfe');
radGrad.addColorStop(1, '#6c5ce7');
ctx.fillStyle = radGrad;
ctx.beginPath();
ctx.arc(150, 150, 80, 0, Math.PI * 2);
ctx.fill();
4.2 阴影效果
javascript
ctx.shadowColor = 'rgba(0,0,0,0.3)';
ctx.shadowBlur = 12;
ctx.shadowOffsetX = 6;
ctx.shadowOffsetY = 6;
ctx.fillStyle = '#0984e3';
ctx.fillRect(100, 100, 120, 80);
// 记得重置阴影避免影响后续绘制
ctx.shadowBlur = 0;
4.3 变换操作
javascript
ctx.save(); // 保存当前状态
ctx.translate(200, 150);
ctx.rotate(Math.PI / 4);
ctx.scale(1.2, 0.8);
ctx.fillStyle = '#fd79a8';
ctx.fillRect(-30, -30, 60, 60);
ctx.restore(); // 恢复状态
5. 动画与帧循环
使用 requestAnimationFrame 实现流畅动画:
javascript
let x = 0;
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#e17055';
ctx.beginPath();
ctx.arc(x, 150, 30, 0, Math.PI * 2);
ctx.fill();
x += 2;
if (x > canvas.width) x = 0;
requestAnimationFrame(draw);
}
draw();
6. 像素操作
使用 getImageData 和 putImageData 进行像素级处理:
javascript
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
// 反色滤镜
for (let i = 0; i < data.length; i += 4) {
data[i] = 255 - data[i]; // R
data[i+1] = 255 - data[i+1]; // G
data[i+2] = 255 - data[i+2]; // B
}
ctx.putImageData(imageData, 0, 0);
7. 性能优化建议
| 优化点 | 说明 |
|---|---|
| 离屏渲染 | 使用 document.createElement('canvas') 绘制复杂内容,再用 drawImage 绘制到主画布 |
减少 clearRect 调用 |
只在需要时清除,或使用多个画布分层 |
避免频繁 save/restore |
批量设置样式,减少状态切换 |
使用 requestAnimationFrame |
替代 setInterval / setTimeout |
| 控制像素操作区域 | 尽量只处理需要更新的矩形区域 |
8. 兼容性与回退
- 所有现代浏览器(Chrome, Firefox, Safari, Edge)均支持 Canvas。
- IE 9+ 支持基础功能,但部分高级特性(如
Path2D)可能不支持。 - 回退方案:在
<canvas>标签内添加备选内容(文本或图片)。
html
<canvas width="400" height="300">
<img src="fallback.png" alt="您的浏览器不支持 Canvas">
</canvas>
9. 实用示例:响应式画布
让画布自适应容器大小,并保持像素比清晰:
javascript
function setupCanvas(canvas) {
const rect = canvas.parentElement.getBoundingClientRect();
const dpr = window.devicePixelRatio || 1;
canvas.width = rect.width * dpr;
canvas.height = rect.height * dpr;
canvas.style.width = rect.width + 'px';
canvas.style.height = rect.height + 'px';
const ctx = canvas.getContext('2d');
ctx.scale(dpr, dpr);
return ctx;
}
10. 总结
| 核心概念 | 描述 |
|---|---|
canvas 元素 |
定义绘图区域,宽高决定分辨率 |
getContext('2d') |
获取 2D 绘图上下文 |
| 路径绘制 | beginPath / moveTo / lineTo / arc |
| 样式控制 | fillStyle / strokeStyle / lineWidth |
| 图像 & 文本 | drawImage / fillText |
| 变换 & 状态 | translate / rotate / save / restore |
| 像素操作 | getImageData / putImageData |
| 动画循环 | requestAnimationFrame |
Canvas 提供了强大且灵活的 2D 绘图能力,结合 JavaScript 可以创造出丰富的交互式图形、数据可视化和游戏体验。掌握它的核心 API 是前端开发进阶的重要一步。