Canvas 无法仅用 ctx.lineTo() 或贝塞尔曲线实现真实绳索,因其缺乏物理模型支撑;必须基于胡克定律、阻尼和节点约束手动构建弹簧系统,才能响应拉力、摆动、碰撞等交互行为。

Canvas 本身不提供绳索物理模型,必须用胡克定律 + 阻尼 + 节点约束手动实现;直接画一条线或贝塞尔曲线只是视觉假象,没有受力反馈和交互响应。
为什么不能只用 ctx.lineTo() 画根“绳子”
单纯绘制路径(比如用 ctx.bezierCurveTo() 拟合弯曲)只是静态图形,无法响应拉力、摆动、切割或碰撞。真实绳索行为依赖节点间弹性力——每个“绳节”是独立可受力的 Node,连接它们的是按胡克定律计算拉力的 Spring 实例。
- 画线只是结果,不是过程;Canvas 不保存“连接关系”,每次重绘都要重新算坐标
- 鼠标拖拽某段时,若无物理模型,其余部分不会自然跟随形变
- 绳子碰到钉子/障碍物时,需实时检测碰撞并分段施加约束,纯绘图做不到
Spring.applyForce() 中必须处理的三个临界值
弹簧力计算稍有不慎就会数值爆炸或卡死。关键不是公式写对,而是边界防护:
- 当前长度
length接近 0 时,跳过力计算或设最小保护值:const safeLength = Math.max(length, 2) - 拉力过大导致节点瞬间飞出画布:在施加力前限制单帧最大位移,例如
force = Math.min(force, 15) - 阻尼系数
damping不能 ≥ 1,否则速度永不衰减;典型值取0.98~0.995,过高则摆动僵硬,过低则振荡发散
如何让绳子“挂住”固定锚点而不漂移
锚点不是靠 CSS 定位,而是通过节点标记 + 更新逻辑绕过物理积分:
立即学习“前端免费学习笔记(深入)”;
- 给锚点节点加字段
isFixed = true,并在每帧Node.update()中直接 return,跳过位置更新 - 但注意:它仍要参与
Spring.applyForce()计算——力会传给另一端的活动节点,只是自身不动 - 若多个锚点共用同一坐标(如顶部横梁),需确保它们不互相施加弹簧力,否则初始微小误差会被放大成抖动
最容易被忽略的是时间步长归一化:用 performance.now() 算 dt,所有力、速度衰减、位移都乘以 dt;否则高刷屏上绳子软绵无力,低刷屏上又猛甩失控。



















