HTML <canvas> 标签(建议收藏)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观

在现代 Web 开发中,HTML <canvas> 标签是一个功能强大的工具,它允许开发者通过 JavaScript 直接操作像素或绘制矢量图形。无论是创建动态图表、游戏、艺术效果,还是实现复杂的交互式可视化,<canvas> 都提供了灵活的解决方案。本文将从基础语法到高级应用,结合实例与代码演示,帮助读者全面理解这一技术的核心概念,并掌握其实际应用场景。


一、基础语法与核心概念

1.1 <canvas> 标签的结构

HTML <canvas> 标签是一个容器元素,用于定义画布的尺寸和位置。其基本语法如下:

<canvas id="myCanvas" width="800" height="600"></canvas>  

这里,id 用于在 JavaScript 中引用画布,widthheight 分别设置画布的宽高(单位为像素)。若未指定尺寸,默认为 300×150 像素。

1.2 绘图上下文(Drawing Context)

要操作画布,必须通过 JavaScript 获取其 绘图上下文。目前 <canvas> 支持两种上下文类型:

  • 2D 上下文:适用于基本的矢量图形绘制(如线条、矩形、文本等)。
  • WebGL 上下文:用于高性能的 3D 图形渲染(需配合 WebGL API)。

获取 2D 上下文的代码示例如下:

const canvas = document.getElementById('myCanvas');  
const ctx = canvas.getContext('2d');  // 2D 上下文  

1.3 坐标系与绘图区域

画布的坐标系以左上角为原点(0,0),x 轴向右延伸,y 轴向下延伸。例如,绘制一个从 (50,50) 开始的矩形:

ctx.fillRect(50, 50, 100, 100);  // 绘制填充矩形  

这类似于在一张纸上用铅笔标记坐标点,然后根据坐标范围填充颜色。


二、2D 绘图 API 核心功能

2.1 基本图形绘制

2.1.1 线条与形状

通过 ctx.beginPath() 开始路径绘制,配合 moveTo()lineTo() 等方法可创建复杂图形:

ctx.beginPath();  
ctx.moveTo(100, 100);  
ctx.lineTo(200, 200);  
ctx.strokeStyle = '#FF0000';  
ctx.stroke();  // 绘制边框  

2.1.2 填充与描边

  • fill():根据当前路径填充颜色。
  • stroke():根据当前路径绘制边框。
  • fillStylestrokeStyle 可设置颜色、渐变或图案:
ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';  
ctx.fillRect(50, 50, 100, 100);  // 半透明绿色矩形  

2.2 变换与动画基础

2.2.1 平移、旋转与缩放

通过 translate()rotate()scale() 方法,可以实现图形的动态变换:

ctx.translate(100, 100);  // 将原点移动到 (100, 100)  
ctx.rotate(Math.PI / 4);  // 旋转 45 度  
ctx.fillRect(0, 0, 50, 50);  

2.2.2 动态动画实现

利用 requestAnimationFrame() 实现流畅动画:

function animate() {  
  ctx.clearRect(0, 0, canvas.width, canvas.height);  // 清空画布  
  // 绘制逻辑(如移动物体)  
  requestAnimationFrame(animate);  
}  
animate();  

三、进阶技巧与实战案例

3.1 响应式画布设计

为适应不同屏幕尺寸,需动态调整画布宽高:

function resizeCanvas() {  
  canvas.width = window.innerWidth * devicePixelRatio;  
  canvas.height = window.innerHeight * devicePixelRatio;  
  canvas.style.width = `${window.innerWidth}px`;  
  canvas.style.height = `${window.innerHeight}px`;  
}  
window.addEventListener('resize', resizeCanvas);  

3.2 实例:绘制动态粒子系统

以下代码实现一个简单的粒子动画:

// 初始化粒子数组  
const particles = [];  
for (let i = 0; i < 100; i++) {  
  particles.push({  
    x: Math.random() * canvas.width,  
    y: Math.random() * canvas.height,  
    speedX: (Math.random() - 0.5) * 2,  
    speedY: (Math.random() - 0.5) * 2,  
    radius: Math.random() * 2 + 1  
  });  
}  

function animate() {  
  ctx.clearRect(0, 0, canvas.width, canvas.height);  
  particles.forEach(p => {  
    ctx.beginPath();  
    ctx.arc(p.x, p.y, p.radius, 0, Math.PI * 2);  
    ctx.fillStyle = '#FFFFFF';  
    ctx.fill();  
    // 更新位置  
    p.x += p.speedX;  
    p.y += p.speedY;  
    // 边界检测  
    if (p.x < 0 || p.x > canvas.width) p.speedX *= -1;  
    if (p.y < 0 || p.y > canvas.height) p.speedY *= -1;  
  });  
  requestAnimationFrame(animate);  
}  

3.3 图像与纹理应用

通过 ctx.drawImage() 可将图片绘制到画布上:

const img = new Image();  
img.src = 'example.jpg';  
img.onload = () => {  
  ctx.drawImage(img, 0, 0, 200, 200);  // 裁剪并缩放图片  
};  

四、性能优化与最佳实践

4.1 减少重绘与重排

  • 避免频繁调用 clearRect(),优先通过覆盖绘制区域。
  • 使用 save()restore() 管理状态,避免重复设置属性。

4.2 复用绘图路径

将复杂路径保存为函数,避免重复计算:

function drawStar(x, y) {  
  ctx.beginPath();  
  ctx.moveTo(x, y);  
  // 绘制星形路径  
  // ...  
  ctx.closePath();  
}  

4.3 可访问性与兼容性

  • 为画布添加 alt 属性或隐藏的 <div> 描述内容,提升可访问性。
  • 使用 toDataURL() 生成图片链接,供不支持 <canvas> 的浏览器使用:
const imgURL = canvas.toDataURL('image/png');  
document.body.innerHTML += `<a href="${imgURL}">下载图片</a>`;  

五、常见问题与解决方案

5.1 画布内容模糊

当缩放画布时,需通过 devicePixelRatio 保持清晰度:

canvas.width = window.innerWidth * window.devicePixelRatio;  
canvas.style.width = `${window.innerWidth}px`;  

5.2 性能瓶颈

  • 减少 requestAnimationFrame 内的复杂计算。
  • 使用 Web Workers 分离后台计算任务。

六、未来展望与扩展方向

随着 WebGL 和 Three.js 的普及,<canvas> 的应用场景已从 2D 扩展到 3D 领域。开发者可通过结合物理引擎(如 Matter.js)或动画库(如 Anime.js),实现更复杂的交互效果。未来,随着 WebGPU 的标准化,<canvas> 的性能与功能将进一步突破,成为 Web 端图形渲染的核心工具。


结论

HTML <canvas> 标签凭借其灵活性与强大功能,成为 Web 开发中不可或缺的图形工具。从基础的矢量绘制到复杂的动画效果,开发者可以通过本文介绍的方法,逐步构建出个性化的可视化解决方案。无论是制作数据图表、小游戏,还是艺术项目,掌握 <canvas> 的核心原理与实践技巧,将为你的 Web 开发之路增添更多可能性。

(全文约 1800 字)

最新发布