HTML5 Canvas:从画图到游戏开发

一、游戏开发的技术演进

在聊 Canvas 之前,先看看网页游戏是怎么一路发展过来的:

阶段 代表 技术特点
页游时代 早期网页游戏 简单图文 + 表单交互
Flash 时代 4399 小游戏 Flash 插件,已淘汰
HTML5 时代 现代 2D/3D 游戏 Canvas + WebGL,浏览器原生支持

Flash 已经退出历史舞台,HTML5 Canvas 成了网页游戏与可视化的事实标准。AI 时代的爆发(three.js 3D 场景、物理大模型可视化)更是把 Canvas 推到了前台。


二、Canvas 是什么?

一句话:HTML5 提供的一块"画布",搭配 JS 绘图 API,想怎么画就怎么画。

与传统 HTML 的区别

  • 普通 HTML 标签(div/p/img):浏览器帮你排版,像"摆积木"
  • Canvas:给你一张白纸 + 一支笔,所有像素由你控制

类似 Photoshop 画布 vs Word 文档的关系。

兼容性

老旧浏览器(IE8 及以下)不支持,但现代浏览器全部原生支持,无需任何插件。


三、Canvas 三步上手

第 1 步:放一块画布

html 复制代码
<canvas id="myCanvas" width="600" height="400" style="border:1px solid #333;">
    <!-- 旧浏览器会显示这段降级文字 -->
    你的浏览器不支持 canvas
</canvas>

⚠️ width/height画布的实际像素尺寸,必须写在标签属性里,不要用 CSS 设置(CSS 设置会拉伸画布导致模糊)。

第 2 步:拿画笔(上下文)

js 复制代码
const canvas = document.querySelector('#myCanvas');
const ctx = canvas.getContext('2d');   // 2D 绘图上下文
// const gl = canvas.getContext('webgl'); // 3D 绘图上下文

上下文(Context)是 Canvas 的核心概念

  • '2d':平面绘图,做 2D 游戏、图表
  • 'webgl':3D 绘图,激发 GPU 显存能力,配合 three.js 做 3D 场景

选哪种 context,决定了你能用哪套 API。

第 3 步:用 API 画图

js 复制代码
ctx.fillStyle = '#4299e1';        // 设置填充颜色
ctx.fillRect(20, 20, 100, 80);    // 画填充矩形:x, y, 宽, 高

ctx.strokeStyle = '#f56565';      // 设置边框颜色
ctx.lineWidth = 4;                // 线宽
ctx.strokeRect(150, 20, 100, 80); // 画边框矩形

ctx.clearRect(50, 50, 40, 30);    // 擦除矩形区域

四、绘图 API 速查

API 作用 参数
fillRect(x, y, w, h) 填充矩形 左上角坐标 + 宽高
strokeRect(x, y, w, h) 边框矩形 同上
clearRect(x, y, w, h) 擦除区域 同上
fillStyle 填充颜色 颜色值
strokeStyle 边框颜色 颜色值
lineWidth 线宽 数字

除了矩形,还能画:

  • arc(x, y, r, 起始角, 结束角)
  • 线moveTo() + lineTo() + stroke()
  • 图片drawImage(img, x, y, w, h)
  • 文字fillText() / strokeText()

五、动画原理:帧动画

核心思想:每秒把画面重画很多次,每次位置稍微变一点,人就看到连续动画了。

浏览器显卡刷新率一般是 60fps(1 秒 60 帧),所以每帧大约 16ms 画一次。

三步循环

复制代码
擦掉上一帧 → 计算新位置 → 画上新内容 → 重复

(一个矩形从左飞到右):

js 复制代码
let x = 20;
const y = 20;
const width = 100;
const height = 80;
const speed = 3;

function animate() {
    // 1. 擦掉整个画布
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    // 2. 画新位置的矩形
    ctx.fillStyle = '#4299e1';
    ctx.fillRect(x, y, width, height);
    // 3. 更新位置
    x += speed;
    // 飞出右边就从左边重新进来
    if (x > canvas.width) {
        x = -width;
    }
    // 4. 请求下一帧
    requestAnimationFrame(animate);
}
animate();   // 启动循环

关键点:不擦除的话,每一帧的矩形会叠在一起,变成一条"拖尾",而不是移动的方块。


六、requestAnimationFrame 详解

为什么不用 setInterval?

方式 问题
setInterval(fn, 16) 定时器是死的,跟屏幕刷新不同步,导致画面撕裂、卡顿、掉帧
requestAnimationFrame(fn) 浏览器智能调度,自动匹配屏幕刷新率(60Hz/120Hz 都行)

额外优势

  1. 自动匹配刷新率:60Hz 屏幕跑 60 次,120Hz 跑 120 次,体验更协调
  2. 后台自动暂停:页面切到后台时停止渲染,省电省性能
  3. 递归调用:参数是一个绘制函数,函数内部再次调用自己

使用范式

js 复制代码
function draw() {
    // 擦 → 算 → 画
    ctx.clearRect(...);
    // 更新状态...
    // 绘制...
    requestAnimationFrame(draw);   // 递归
}
draw();

帧动画不停的画,就有了动画;加上交互,就有了游戏。


七、飞机游戏开发流程

整个流程是:

1. 工程初始化

bash 复制代码
npm create vite@latest airplane -- --template vanilla
cd airplane
npm install
git init
  • Vite:现代前端构建工具,热更新快
  • Git:版本管理
  • .env:存放 API key 等环境变量

2. 与 Claude Code 头脑风暴

这一步是 AI 时代的开发新姿势:

  • 产品功能列表:让 AI 帮你列出游戏可能的功能
  • MVP(最小可行性方案):选其中几个核心功能做第一阶段
  • 技术路线:用什么库?架构怎么设计?
  • 技术方案:最终落地的实现细节

3. LLM 生成代码

把方案确定后,让 LLM 生成具体代码,再人工调整。

💡 这套流程的核心思想:AI 不只是写代码工具,更是产品经理 + 架构师


八、数据可视化:ECharts

Canvas 除了做游戏,另一个超级应用是数据可视化。ECharts 就是底层基于 Canvas 的图表库。

js 复制代码
import * as echarts from 'echarts'

const chartDom = document.getElementById('chart')
const chart = echarts.init(chartDom)   // 初始化图表实例

const option = {
  title: { text: '运动鞋月度销售额', left: 'center' },
  tooltip: { trigger: 'axis' },        // 鼠标悬浮提示
  xAxis: { type: 'category', data: months },   // X 轴
  yAxis: { type: 'value' },                    // Y 轴
  series: [{
    name: '销售额',
    type: 'bar',                        // 柱状图
    data: salesValues,
    itemStyle: { borderRadius: [6, 6, 0, 0] }
  }]
}

chart.setOption(option)   // 应用配置
window.addEventListener('resize', () => chart.resize())  // 响应式

ECharts 的优势

  • 不用手写 Canvas 绘图 API,配置式开发
  • 内置几十种图表:柱状图、折线图、饼图、地图、3D 图
  • 底层自动用 Canvas/WebGL 渲染,性能好

九、知识图谱总结

arduino 复制代码
HTML5 Canvas
├── 基础
│   ├── <canvas> 标签(width/height 像素尺寸)
│   ├── getContext('2d' | 'webgl') 上下文
│   └── 绘图 API(fillRect / strokeRect / clearRect / arc / drawImage...)
│
├── 动画
│   ├── 帧动画三步:擦 → 算 → 画
│   ├── requestAnimationFrame(不用 setInterval)
│   └── 60fps 屏幕刷新率
│
├── 应用场景
│   ├── 2D 游戏(飞机大战)
│   ├── 3D 场景(three.js + WebGL)
│   ├── 数据可视化(ECharts)
│   └── 图片处理 / 签名板 / 特效
│
└── 开发流程(AI 时代)
    ├── Vite 工程化
    ├── 与 CC 头脑风暴 → MVP
    └── LLM 生成代码

相关推荐
cindershade1 小时前
用 Web Workers 优化前端重计算任务:避免主线程卡顿的实战方案
前端
爱丶不疚1 小时前
搞不清 CommonJS 与 ESM,你是否也有这些疑问🤔
前端·node.js
YIAN1 小时前
http无状态?State来展示!从基础路由到鉴权守卫,吃透 SPA 前端路由核心
前端·react.js
__zRainy__1 小时前
Node系列 · Node基础:全局变量与全局对象
开发语言·前端·javascript
码云骑士1 小时前
104-实战论文搜索引擎-ArXiv爬取-Milvus存储-RAG问答-Gradio前端
前端·python·搜索引擎·milvus
sunly_1 小时前
TypeScript总结:15、类型速查
前端·javascript·typescript
Brown.alexis1 小时前
es6知识点3-自备使用
前端·javascript·es6
2601_953988071 小时前
Ricon组态系统vs传统组态软件:为什么选择新一代Web组态平台
前端·后端·物联网·tcp/ip·数学建模·前端框架
天空之城--1 小时前
Claude Code 高效开发 Web 2D/3D 完全指南:心法、自定义 Skill 体系与社区技能包实战
前端·3d