跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
JavaScript大前端

前端 Canvas 基础绘图与动画实战

前端 Canvas 的基础知识与实战应用。内容涵盖常见误区解析、Canvas 的优势(如高性能、交互性、跨平台),并通过代码示例展示了基础绘制、动画实现(使用 requestAnimationFrame)、交互事件处理、数据可视化图表绘制以及图像处理(如灰度滤镜)。文章强调了正确使用 Canvas 的方法,包括避免频繁重绘、合理管理画布尺寸及利用相关工具库,旨在帮助开发者掌握 Canvas 技术以提升网站的视觉表现力。

CloudNative发布于 2026/4/6更新于 2026/9/1277 浏览

前端 Canvas 基础绘图与动画实战

常见误区

前端 Canvas 常被误认为仅用于游戏开发。

  • 'Canvas 性能差'——忽略了其直接操作像素的高性能特性;
  • 'Canvas 太复杂'——导致只能使用静态图片;
  • '用 CSS 就够了'——无法实现复杂的动态效果。

实际上,Canvas 不仅限于游戏,前端同样可以利用它创建丰富的视觉效果。

为什么需要 Canvas?

  • 丰富的视觉效果:创建动态图形、动画和游戏;
  • 高性能:直接操作像素,渲染效率高;
  • 交互性:支持鼠标、触摸等事件交互;
  • 数据可视化:绘制图表、仪表盘等;
  • 跨平台:在所有现代浏览器中运行。

错误示例

// 错误示例:简单的 Canvas 绘制
function drawCircle() {
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');
  // 绘制一个简单的圆形
  ctx.beginPath();
  ctx.arc(100, 100, 50, 0, Math.PI * 2);
  ctx.fillStyle = 'red';
  ctx.fill();
  ctx.stroke();
}

// 错误示例:没有优化的动画
function animate() {
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext();
   x = ;
  ( {
    
    ctx.(, , canvas., canvas.);
    
    ctx. = ;
    ctx.(x, , , );
    x += ;
     (x > canvas.) { x = ; }
  }, );
}
'2d'
let
0
setInterval
() =>
// 每次都清除整个画布
clearRect
0
0
width
height
// 绘制移动的矩形
fillStyle
'blue'
fillRect
50
50
50
1
if
width
0
16

正确实现

// 正确实现:Canvas 基础绘制
function basicDrawing() {
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');
  // 设置画布尺寸
  canvas.width = 800;
  canvas.height = 600;
  // 绘制矩形
  ctx.fillStyle = 'blue';
  ctx.fillRect(50, 50, 100, 100);
  // 绘制圆形
  ctx.beginPath();
  ctx.arc(250, 100, 50, 0, Math.PI * 2);
  ctx.fillStyle = 'red';
  ctx.fill();
  // 绘制路径
  ctx.beginPath();
  ctx.moveTo(350, 50);
  ctx.lineTo(450, 150);
  ctx.lineTo(350, 150);
  ctx.closePath();
  ctx.strokeStyle = 'green';
  ctx.lineWidth = 2;
  ctx.stroke();
  // 绘制文本
  ctx.font = '24px Arial';
  ctx.fillStyle = 'black';
  ctx.textAlign = 'center';
  ctx.fillText('Canvas 绘制示例', canvas.width / 2, 30);
}

// 正确实现:Canvas 动画
function canvasAnimation() {
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');
  canvas.width = 800;
  canvas.height = 600;
  let x = 0;
  let y = canvas.height / 2;
  let dx = 2;
  let dy = 2;
  const radius = 20;

  function animate() {
    // 清除画布
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    // 绘制移动的圆形
    ctx.beginPath();
    ctx.arc(x, y, radius, 0, Math.PI * 2);
    ctx.fillStyle = 'purple';
    ctx.fill();
    // 边界检测
    if (x + radius > canvas.width || x - radius < 0) { dx = -dx; }
    if (y + radius > canvas.height || y - radius < 0) { dy = -dy; }
    // 更新位置
    x += dx;
    y += dy;
    // 使用 requestAnimationFrame
    requestAnimationFrame(animate);
  }
  animate();
}

// 正确实现:Canvas 交互
function canvasInteraction() {
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');
  canvas.width = 800;
  canvas.height = 600;
  let isDrawing = false;
  let lastX = 0;
  let lastY = 0;

  // 鼠标按下事件
  canvas.addEventListener('mousedown', (e) => {
    isDrawing = true;
    [lastX, lastY] = [e.offsetX, e.offsetY];
  });

  // 鼠标移动事件
  canvas.addEventListener('mousemove', (e) => {
    if (!isDrawing) return;
    ctx.beginPath();
    ctx.moveTo(lastX, lastY);
    ctx.lineTo(e.offsetX, e.offsetY);
    ctx.strokeStyle = 'black';
    ctx.lineWidth = 2;
    ctx.stroke();
    [lastX, lastY] = [e.offsetX, e.offsetY];
  });

  // 鼠标释放事件
  canvas.addEventListener('mouseup', () => {
    isDrawing = false;
  });

  // 鼠标离开事件
  canvas.addEventListener('mouseout', () => {
    isDrawing = false;
  });
}

// 正确实现:Canvas 数据可视化
function canvasChart() {
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');
  canvas.width = 800;
  canvas.height = 600;

  // 数据
  const data = [12, 19, 3, 5, 2, 3, 7, 11, 15, 18, 10, 6];
  const labels = ['1 月', '2 月', '3 月', '4 月', '5 月', '6 月', '7 月', '8 月', '9 月', '10 月', '11 月', '12 月'];

  // 绘制坐标系
  const padding = 50;
  const chartWidth = canvas.width - padding * 2;
  const chartHeight = canvas.height - padding * 2;

  // X 轴
  ctx.beginPath();
  ctx.moveTo(padding, canvas.height - padding);
  ctx.lineTo(canvas.width - padding, canvas.height - padding);
  ctx.stroke();

  // Y 轴
  ctx.beginPath();
  ctx.moveTo(padding, padding);
  ctx.lineTo(padding, canvas.height - padding);
  ctx.stroke();

  // 绘制数据
  const maxValue = Math.max(...data);
  const barWidth = chartWidth / data.length;
  data.forEach((value, index) => {
    const barHeight = (value / maxValue) * chartHeight;
    const x = padding + index * barWidth;
    const y = canvas.height - padding - barHeight;
    // 绘制柱子
    ctx.fillStyle = 'rgba(54, 162, 235, 0.6)';
    ctx.fillRect(x + 5, y, barWidth - 10, barHeight);
    // 绘制标签
    ctx.font = '12px Arial';
    ctx.fillStyle = 'black';
    ctx.textAlign = 'center';
    ctx.fillText(labels[index], x + barWidth / 2, canvas.height - padding + 15);
  });

  // 绘制标题
  ctx.font = '20px Arial';
  ctx.fillStyle = 'black';
  ctx.textAlign = 'center';
  ctx.fillText('月度销售数据', canvas.width / 2, padding / 2);
}

// 正确实现:Canvas 图像处理
function canvasImageProcessing() {
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');
  canvas.width = 800;
  canvas.height = 600;

  // 加载图像
  const img = new Image();
  img.crossOrigin = 'anonymous';
  img.onload = () => {
    // 绘制原始图像
    ctx.drawImage(img, 0, 0, 400, 300);
    // 获取图像数据
    const imageData = ctx.getImageData(0, 0, 400, 300);
    const data = imageData.data;
    // 处理图像(灰度)
    for (let i = 0; i < data.length; i += 4) {
      const r = data[i];
      const g = data[i + 1];
      const b = data[i + 2];
      const gray = (r + g + b) / 3;
      data[i] = gray;
      data[i + 1] = gray;
      data[i + 2] = gray;
    }
    // 绘制处理后的图像
    ctx.putImageData(imageData, 400, 0);
  };
  img.src = 'https://picsum.photos/800/600';
}

技术总结

Canvas 是一个强大的工具,可用于创建从简单图表到复杂游戏的各种视觉效果。

  • 基础绘制:矩形、圆形、路径、文本等;
  • 动画效果:使用 requestAnimationFrame 实现流畅动画;
  • 交互操作:鼠标、触摸等事件处理;
  • 数据可视化:绘制图表、仪表盘等;
  • 图像处理:像素级操作,实现滤镜效果;
  • 性能优化:合理使用缓存、避免频繁重绘;
  • 响应式:根据容器大小调整画布尺寸;
  • 工具库:使用 Chart.js、Fabric.js 等库简化开发。

前端 Canvas 是构建高质量 Web 视觉体验的关键技术之一。

目录

  1. 前端 Canvas 基础绘图与动画实战
  2. 常见误区
  3. 为什么需要 Canvas?
  4. 错误示例
  5. 正确实现
  6. 技术总结

更多推荐文章

查看全部
  • SQL Server 到 KingbaseES V9R4C12 的零改造迁移实战
  • n8n Webhook 节点实战教程:从入门到生产级部署
  • Spring AI MCP Server 集成与源码解析
  • VSCode 配置 GitHub Copilot 使用 OpenAI 兼容模型指南
  • 医学大模型的实战场景:临床辅助、科研提效与教育变革
  • 多模态模型开发与应用:文本、图像与语音融合实践
  • Raphael AI:基于 Flux 模型的在线 AI 图像生成工具
  • JavaScript 基础语法与 jQuery 实战指南
  • Git 代码上传 Gitee 实战指南
  • 基于 DroneVehicle 数据集的 YOLOv11 无人机车辆目标检测
  • 2026 年 1 月主流远程桌面工具横向评测与选型建议
  • Stable Diffusion 提示词使用指南
  • OpenClaw 多 Agent 与多飞书机器人配置实践
  • 前端开发:如何使用浏览器开发者工具查看接口请求与响应
  • C++11 左值右值引用区别与移动语义解决传值返回对象销毁问题
  • JavaScript Headers 对象特性与 Request 使用指南
  • 4S 店车辆管理系统的设计与实现
  • OpenHarmony 下 Flutter 跨域难题:flutter_cors 实战与适配方案
  • 通义千问插件在 IDEA 中的 Java 开发实战应用
  • Web 应用架构与常见安全漏洞解析

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online