HTML canvas标签使用指南-Day32

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 是前端开发进阶的重要一步。

相关推荐
锋行天下6 小时前
DeepSeek写Langgraph就是个大傻逼,一本正经胡说八道
前端·人工智能·后端
jktantan6 小时前
每个节点 41 字节:把一棵百万节点树拆进 14 个 typed array
前端·javascript·vue.js·算法·typescript
计算机魔术师7 小时前
Anthropic官方插件被「寄生」,背后是同一类攻击又来了
前端
我命由我123457 小时前
访客系统形式(有用户概念、无用户概念)
java·开发语言·前端·javascript·python·产品运营·产品经理
key_3_feng7 小时前
评估与对齐:Agent 自我进化的护栏
前端·数据库·agent
LaughingZhu8 小时前
Product Hunt 热榜 2026-10-30:Empacer、Scape、Floot in ChatGPT
java·前端·数据库·人工智能·chatgpt·notion
Lank_M8 小时前
抠图结果缩放后边缘发脏,该怪的不是插值
前端
jerrywus8 小时前
Skill、MCP、Workflow、Rules、Memory 有什么区别?拿几次真实开发任务讲清楚
前端·agent·claude
补码缩写8 小时前
canvas 与 sharp 缩放透明图:默认预乘,非预乘得拆通道
前端
静默回滚8 小时前
抠图 PNG 缩小再放大,边缘又糊又白是两件事
前端