- Add Netlify deployment section with form handling and functions examples - Replace old Git demos with new interactive components - Add comprehensive data encoding visualization demos - Update comparison table with Netlify information
8.5 KiB
图形与动画(Canvas 与他的朋友们)
::: tip 🎯 核心问题
以前的网页只能展示干巴巴的文字和图片。但如果你想做打砖块游戏、华丽的动态特效、或是可以自由拖拽的数据报表呢?这就是 Canvas(画布) 诞生的原因。
:::
1. 什么是 Canvas?
如果说早期的那些 HTML 标签(如 <div>、<img>)是用乐高积木拼起一个静态的网页,那么 HTML5 的 <canvas> 标签就是扔给你一张巨大的数字白纸,然后递给你一支靠代码控制的画笔,剩下的全交给你自由发挥。
这里面的画没有任何标签结构,你用画笔涂上去的心血,一旦落笔就变成了最纯粹的**“像素颜料”**。
1.1 Canvas vs SVG:两种不同流派的艺术家
在前端画图界,Canvas 有个宿敌叫 SVG。它们代表了两种截然不同的绘画观念:
Canvas(位图画板):
- 原理:就像真实在纸上涂色,几笔画上去就变成一团颜料。
- 优势:电脑只管往屏幕上“洒颜料”,性能起飞!能同时画出大几千个活蹦乱跳的闪烁粒子。
- 缺点:画完就没法单独反悔(没法被 DOM 直接选择),而且你用浏览器一旦放大,画面就会马赛克发虚。
SVG(矢量图拼接):
- 原理:就像在做幻灯片(PPT)。你画一个圆,它就生成一个圆圈的“实体对象”放在画面上。
- 优势:不管被放大成 100 倍还是 10 万倍,永远极其清晰。而且因为每一个形状都是一个独立标签,你可以在任何时候用鼠标点中某个小正方形,命令它换一种颜色。
- 缺点:如果你试图放几万个对象乱飞,繁重的排版引擎会直接把浏览器卡死。
🎮 简单总结:玩动态游戏、做酷炫粒子特效用 Canvas;画精密的 Logo、写交互清晰的小图表用 SVG。
2. 第一笔:用代码找坐标
2.1 这张纸的上下怎么颠倒了?
当你准备下笔时,得先明白 Canvas 里的尺子是反着的。对于传统的数学课坐标系,中心点零点在中间,越往上越大。
但在屏幕显示领域,几乎所有设备的“原点(0,0)”都定在屏幕的最左上角。向右走 X 轴变大没问题,但是向下走,Y 轴变大。
👇 动手点点看: 拖拽下面的这些点,直观地感受一下坐标是如何变化的:
2.2 给你的魔法画笔上调料
有了坐标,我们就能召唤那支画笔了(在代码里这支笔叫 Context 或简称 ctx)。
就像拿着调色盘作画,流程总是固定的三步:
- 调色:告诉它你需要什么填充色(
fillStyle)和描边色(strokeStyle) - 构形:构思你是画一个圈、还是一条直线?
- 下笔:实打实地去填充(
fill( ))还是去勾勒边缘(stroke( ))
👇 动手点点看: 试试把下面代码面板里的形状颜色换换:
3. 翻页动画书:如何让画面动起来极度丝滑
我们刚才说过,Canvas 一旦你填上了颜色,这就变成了永久的马赛克。你怎么可能让马赛克奔跑呢?
答案是“骗过你的眼睛”。这和翻页手翻书或者电影胶片的原理一模一样。
如果你想让一个球飞起来:
- 擦黑板:用
clearRect把这整块画布上的内容毫不留情地清空! - 挪位置:让那个球的 X 坐标往前偷偷加 2 毫米。
- 下笔重画:把球在新的位置重新画一次。
- 疯狂循环:浏览器内置了一个极其精准的神仙秒表叫
requestAnimationFrame。它会以每秒 60 次(即 60 FPS)的变态速度,重复着【擦除 -> 移动 -> 重绘】。由于人眼自带“视觉残留”,你在屏幕上看到的,不仅不是黑板被擦,反而是如同丝绸般顺滑的动画。
👇 动手点点看: 尝试添加或者减少物体的数量,感受每秒 60 帧带来的无缝快感:
4. 瞎子摸象:我在 Canvas 里面怎么点击?
因为 Canvas 画布就只是一张没有任何结构的“颜料布”。假设你在这个布上画了一只哥布林:
如果你想写个代码:“当玩家点中了哥布林,哥布林阵亡”。你根本没法像写普通网页那样通过 getElementById 去直接绑定这个外星怪物。因为在浏览器的眼里,这里永远没有任何怪兽,只有一块宽 600 高 400 的 <canvas> 标签死死挡在这里。
那我们要怎么做事件交互呢?
- 监听布面被点:先获取你目前鼠标点在这个死板的 HTML 大布的哪个具体的 XY 位置。
- 拿账本去对:然后你必须自己翻你的代码记录,“我记得刚刚我在(100,100)的位置画了一个半径 50 的哥布林”。
- 勾股定理:我们用初中教的勾股定理公式去疯狂计算——当前鼠标点击的位置,是不是落在了那个(100,100)距离 50 半径的圆内?。
恭喜你!这种疯狂算几何数学距离的方法就是你在各大 3A 游戏里听过的 “碰撞检测 (Collision Detection)”
👇 动手点点看: 打开最下面的“Hover 悬停模式”,你就能看到它内部拼命去算距离有多累了。
5. 解放算力:粒子系统与视觉魔法
到了这一步,当你把【坐标不断重绘的动画】跟【颜色和大小变换】融合,再放进成百上千个小碎片里。这就是引爆视觉的终极杀器:粒子系统。
你只需要建立一个巨大的数组,里面塞满了几百个拥有独立生命值、独立初始随机速度的数字对象。每次“重绘”,让所有的点根据重力或者惯性去减速。你的浏览器里马上就能发生逼真的大爆炸或者漫天飞雪。
👇 动手点点看: 试试“烟花”和“鼠标轨迹”!
6. 守护 FPS 荣耀:如何应对高烧的 CPU?
让成千上万个对象在一秒内计算重画 60 遍,这是极其消耗电脑算力(CPU 和内存)的。 很多野生小白刚做出来的游戏玩了两分钟可能风扇就起飞了。下面是真正的引擎大佬使用的降温护体绝技:
- 局部擦黑板(脏矩形 Dirty Rect)! 一个角色在一望无际的草原上奔跑。你千万别每帧把整块大草原都擦了重画!角色经过哪一小块,你就用小板擦把哪里擦掉然后只补哪里的洞,这能省下几千倍的力气。
- 隐藏后台魔法(离屏 Canvas)! 如果游戏背景是繁星漫天、有各种复杂绚丽的山脉。最好先偷偷在没人的后台建一个内存 Canvas 把它一次性精美地画上去。以后每秒 60 下的刷新,你直接把这幅“定格全图”通过贴图的方式贴到前端(
drawImage)就行了。 - 批量洗画笔! 如果画画时你要反复交替使用“红、蓝、红、蓝、红”这几种笔,频繁切换。可以提前把所有红色的兵全归档画完,再清空换蓝颜料画,省去了昂贵的上下文来回切换。
👇 动手点点看: 先把对象数量拉满,看着网页快掉进卡顿的深渊,再依次打开右下方的绝技进行抢救。
7. 名词对照表
| 术语 | 解释 |
|---|---|
| Canvas | Html5 提供的 2D 画布。绘制极快,但画完就变成颜料像素,不支持通过 DOM 操作内容。 |
| SVG | 矢量图,放大永远不模糊,且每个图形都是独立的标签元素可以单独点击绑定事件。 |
| Context (ctx) | 获取到的“2D 上下文”,可以理解为用来在这张布上调各种颜色、干各种特殊效果的“画笔”。 |
| requestAnimationFrame | 浏览器内置的神级节拍器,会以显示器的刷新率(通常 60FPS)不断狂飙执行,专门用来做完美动画。 |
| FPS / Frame Rate | 帧率。60 FPS 代表一秒钟内浏览器帮我们默默擦除了 60 次黑板并画了 60 副新图,这骗过了视神经,看起来极其丝滑。 |
| Dirty Rect / 脏矩形 | 只在画面中发生变化的微小矩形区域内进行擦除和重绘,强力保留性能。 |
| Offscreen Canvas | 藏在内存里的“影子画布”,把静态且复杂的树木和山脉先画好,当作死的一张贴图重复利用。 |
现在,不管是一把简单的魔法画笔、还是由万千雪花组成的宏大粒子系统,整个能够不断刷新重绘的数字世界引擎,都在你的掌控之中了!