悟夕导航

第八集:项目复盘——画一只猫,结果画成猪?

97 0 0
“老板要‘可爱卡通猫’,我交付了‘会扭屁股的猪’,他说:‘上线!’”
—— 某位把 KPI 画成曲线并成功升职的前端小可爱

大家好,欢迎来到《Canvas 翻车指南》终章
前面七集我们把 Canvas 从入门玩到性能怪兽,今天串成通关连招

  • 需求 → 原型 → 技术选型 → 踩坑 → 优化 → 上线
  • 一只猫(最后像猪)的交付过程,复盘真实项目流程
  • 开源《Canvas 翻车指南》仓库,Star 破千直播“画 KPI 曲线,画不好扣工资”

准备好啤酒,我们一起把翻车写成文档把 bug 写成段子


一、需求阶段:一句话的“可爱”

老板原话:

“要一只会扭屁股可爱卡通猫,放在首页,吸引人点按钮。”

翻译需求:

  1. 矢量画风(放大不虚)
  2. 60 FPS 扭动(丝滑)
  3. 可配置(万一明天要狗)
  4. 包体积 < 100 KB(3G 用户也配看猪)

复盘:

“可爱” 没有量化指标,最终验收以老板嘴角上扬 30° 为准

二、技术选型:2D vs WebGL vs SVG

方案优点缺点结论
SVG + CSS矢量、无需像素DOM 太多掉帧扭动关节要 <animate>代码量爆炸
Canvas 2DAPI 简单大量曲线重绘 CPU 占满适合中等规模
WebGLGPU 加速包体积大、上手难为了 60 FPS 值得

最终:
WebGL + 少量 2D 兜底着色器里画圆当关节一只猫=10 个圆+1 条贝塞尔尾巴

口诀:

“老板要矢量,GPU 最矢量。”

三、原型设计:Figma → 坐标 → 顶点

  1. Figma 画草图:头、身体、耳朵、尾巴均用圆+圆角矩形
  2. 导出 SVG 路径转贝塞尔坐标
  3. 写脚本pathvec2 数组,直接塞进 WebGL buffer

结果:
设计到代码 1:1 还原设计师都惊了,“原来我画的圆真能跑”。


四、开发阶段:猫 → 猪 的 morph 轨迹

1. 骨架系统(Skeleton)

interface Bone {
  parent?: Bone;
  length: number;
  angle: number;
  pivot: Vec2; // 本地坐标
}

头、身、耳朵、尾巴各一个 Bone层级联动

2. 扭屁股动画

requestAnimationFrame 每帧改 angle

function wiggle(t: number) {
  bones.tail.angle = Math.sin(t) * 20; // 尾巴甩
  hips.angle = Math.sin(t * 0.7) * 10; // 屁股扭
}

扭起来像电臀舞可爱值 +999

3. 着色器画圆当关节

顶点着色器:

attribute vec2 a_position;
attribute float a_size;
uniform vec2 u_resolution;
void main() {
  vec2 clip = (a_position / u_resolution) * 2.0 - 1.0;
  gl_Position = vec4(clip * vec2(1,-1), 0, 1);
  gl_PointSize = a_size;
}

片元裁圆:

if (length(gl_PointCoord - 0.5) > 0.5) discard;

一只猫 = 10 个圆一次 drawArrays 搞定CPU 0 计算


五、第一次翻车:老板说不像猫,像猪

原因盘点:

问题现场解决方案
耳朵太短像猪耳朵放大 1.5 倍,角度朝前
鼻子粉色圆像猪鼻子改三角形,用 TRIANGLES
身体太圆像猪肚子拉长 0.8 倍,椭圆
尾巴卷度像猪尾巴贝塞尔加 2 个控制点,S 型

改完直接猪猫合体老板嘴角上扬 30°验收通过


六、性能优化:从 60 FPS 到 144 FPS

  1. OffscreenCanvas + Worker
    物理与渲染放后台,主线程刷微博也不掉帧
  2. 顶点压缩
    vec2 positionInt16Array显存减半
  3. LOD(细节层次)
    小屏设备把圆点数 10 → 6,肉眼无感帧率翻倍
  4. 包体积

    • GLSL 压缩 glsl-minifier-30%
    • Worker 代码 gzip18 KB
    • < 83 KB3G 用户 2 秒加载完

七、可配置化:猫狗一键切换

export interface PetOption {
  type: 'cat' | 'dog';
  primaryColor: string;
  wiggleSpeed: number;
}

改 1 个 prop重新生成顶点热更新 0.3 秒看到狗

设计师:“以后节日换皮肤,不用求你!”


八、上线与数据

指标数值备注
首屏加载1.8 s3G 网络
交互延迟16 msRAF 稳 60 FPS
按钮点击率↑ 27 %对比静态猫
包体积83 KBgzip
老板嘴角30°验收达标

九、复盘清单(Checklist)

  1. 需求量化:把“可爱”拆成圆数量、扭动角度、帧率
  2. 设计先行:Figma → 坐标脚本,减少手写试错
  3. 技术选型:WebGL 虽重,但GPU 矢量=未来
  4. early 演示:第 3 天给老板看灰模扭动收集反馈越早越好
  5. 性能预算:给自己设< 100 KB、> 55 FPS超了立即优化
  6. 可配置props 即皮肤节日活动不求人

十、彩蛋:直播画 KPI 曲线

仓库地址(已开源):
https://github.com/yourname/canvas-failure-guide

Star 破 1000
作者直播用 Canvas 画公司季度 KPI 曲线画不好当场扣工资欢迎围观


终章结语

“从一条蚯蚓直线,到十万星空粒子,再到一只扭屁股的猪猫——
我们一路翻车,一路修锅,终于把 Canvas 这匹野马,套上了框架的缰绳。
愿你在今后的项目里,少掉两根头发,多涨一次工资
记住:人生就像贝塞尔曲线,弯过去,就是彩虹。”

全文终感谢陪伴江湖再见,点个 Star 再走吧

0
快来点个赞吧

发表评论

隐私评论

评论列表

来写一个评论吧