弹性菜单核心是用胡克定律+阻尼衰减实现真实物理运动,每帧通过欧拉法更新位置与速度,配合坐标映射、极坐标扇形展开及 requestanimationframe 渲染,确保自然回弹与高性能。

直接用 Canvas 模拟弹性菜单,核心不是“画得像”,而是让菜单项的运动符合胡克定律 + 阻尼衰减的真实物理逻辑。它比 CSS 的 cubic-bezier 更自然,松手后有回弹、微震荡、渐停的过程,适合做扇形展开、侧边栏抽拉、图标悬浮弹出等交互。
构建弹性物理模型
每个菜单项(比如一个扇形按钮或图标)都需维护三个关键变量:
-
当前位置(
x,y):当前渲染坐标 -
当前速度(
vx,vy):决定下一帧移动多远 -
目标位置(
targetX,targetY):用户交互触发后希望它最终停靠的位置(如展开后的中心点)
每帧用欧拉法迭代更新:
- 速度更新:
vx += (targetX - x) * k - vx * d - 位置更新:
x += vx
其中 k 是劲度系数(越大越“硬”,回弹越快),d 是阻尼系数(0.85~0.98 之间较自然;太小会不停抖动,太大则发滞)。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
绑定用户交互事件
Canvas 本身不自带 DOM 级别点击检测,需手动做坐标映射和命中判断:
- 监听
mousedown/touchstart,记录初始点击位置 - 在
mousemove/touchmove中实时更新菜单项的targetX/targetY(例如拖拽时让它跟随鼠标) - 在
mouseup/touchend后,将targetX/targetY切换为预设的“收起”或“展开终态”坐标,让物理系统自动收敛
若做扇形菜单,可把各菜单项的目标角度映射到极坐标,再转为屏幕坐标,这样展开/收拢时弧线轨迹更自然。
Canvas 渲染与性能要点
动画必须走 requestAnimationFrame,避免 setTimeout 导致步长不稳,破坏物理感:
- 清屏用
ctx.clearRect(0, 0, canvas.width, canvas.height),不要用fillRect覆盖背景(易残留) - 绘制菜单项时,优先用
ctx.beginPath() → ctx.arc() → ctx.fill()或路径组合,避免频繁创建临时对象 - 若菜单项含文字或图标,建议提前缓存为
OffscreenCanvas或ImageBitmap,减少每帧重绘开销
避免常见误区
很多人试图用 Canvas “模拟 CSS transition”,结果卡顿或失真。关键区别在于:
- 不依赖元素
left/top,所有状态纯 JS 管理,只在渲染阶段写入ctx - 不把弹性逻辑塞进事件回调里——物理计算和渲染分离,计算在
animate内完成 - 鼠标坐标需通过
getBoundingClientRect()转为相对于 Canvas 的坐标系,否则缩放或滚动页面时会错位
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










