You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在HTML5 Canvas中实现图像的平滑移动动画?

实现Canvas图像平滑移动的解决方案

这个问题很常见——你当前的实现是点击后直接一次性修改位置并触发单次重绘,所以图像看起来是跳跃式移动的。要实现平滑的动画效果,我们需要利用浏览器原生的 requestAnimationFrame API 创建持续的帧更新循环,让图像在每一帧中移动一小段距离,逐步接近目标位置。

具体修改步骤:

  1. 重构状态变量
    我们需要区分「当前位置」和「目标位置」,同时定义移动速度(控制平滑度):

    // 初始位置(和你原来的默认值一致)
    let currentLeft = 100;
    // 目标位置,初始和当前位置相同
    let targetLeft = currentLeft;
    // 每帧移动的像素数,值越小越平滑,越大移动越快
    const moveSpeed = 2;
    
  2. 修改点击事件逻辑
    点击时不再直接修改位置,而是更新目标位置:

    $("#left").on("click", function(){
      // 每次点击,目标位置向右移动10像素(如果要左移就改成 -=10)
      targetLeft += 10;
    });
    
  3. 创建动画循环
    用 requestAnimationFrame 实现持续的帧更新,在每一帧中逐步调整当前位置并重新绘制图像:

    function animate() {
      // 先清除画布,避免图像留下轨迹
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      
      // 逐步接近目标位置
      if (currentLeft < targetLeft) {
        currentLeft += moveSpeed;
        // 防止超过目标位置
        if (currentLeft > targetLeft) currentLeft = targetLeft;
      } else if (currentLeft > targetLeft) {
        currentLeft -= moveSpeed;
        if (currentLeft < targetLeft) currentLeft = targetLeft;
      }
      
      // 绘制图像(用currentLeft作为当前位置)
      ctx.drawImage(img, 0, 0, imgW, imgH, currentLeft, 0, imgW, imgH);
      
      // 循环调用,保持动画持续运行
      requestAnimationFrame(animate);
    }
    
    // 启动动画循环
    animate();
    

为什么这样能实现平滑效果?

requestAnimationFrame 会按照浏览器的刷新频率(通常60帧/秒)调用动画函数,每帧只移动几个像素,视觉上就会呈现出连续平滑的移动效果,而不是一次性跳跃10像素。

关于你提到的GlassesUp逻辑

你提到的眼镜移动(GlassesUp)也可以用完全相同的思路:定义currentUp、targetUp和移动速度,点击时更新targetUp,然后在同一个animate函数中处理垂直方向的位置更新即可。

内容的提问来源于stack exchange,提问作者joe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:50:41