无限滚动背景的关键是双图复用与位置偏移:两张图并排绘制,持续移动x坐标,一张移出时立即重置到另一张末端,确保无缝循环;需图像宽度为画布整数倍、预加载图片、取整坐标防抖动。

Canvas实现无限滚动背景的关键在于“双图复用+位置偏移”,而不是不断绘制新图像。核心思路是用两张相同背景图并排绘制,通过持续移动它们的横坐标,当一张图完全移出画布时,立刻将其重置到另一张图的末端,形成视觉上的无缝循环。
双图定位与偏移控制
创建两个相同的背景图像实例,初始时左图x=0,右图x=width(即紧贴左图右侧)。每帧按固定速度(如-2)更新两图的x坐标:
- 左图x += speed;右图x += speed
- 若左图x ≤ -width,说明它已完全左移出画布,立即将其x重置为右图x + width
- 若右图x ≤ -width,则重置为左图x + width
这样两张图始终一前一后覆盖整个画布宽度,且无空隙、无跳变。
确保图像尺寸与画布匹配
无缝滚动的前提是背景图在水平方向能整除画布宽度,否则拼接处会出现错位或拉伸:
立即学习“前端免费学习笔记(深入)”;
- 推荐背景图宽度设为画布宽度的整数倍(如画布800px,背景图1600px)
- 使用
drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh)精确控制绘制区域,避免因缩放导致像素偏移 - 若必须缩放,确保
dw / img.width === dh / img.height,保持宽高比一致
优化性能:避免重复加载与重绘
背景图只需加载一次,绘制时复用同一Image对象。将图片预加载完成后再启动动画循环:
- 用
img.onload = () => { startAnimation(); }确保图像就绪 - 在
requestAnimationFrame回调中仅执行位移计算和drawImage,不重复创建Canvas或Image - 清除前一帧用
ctx.clearRect(0, 0, canvas.width, canvas.height),而非重绘整个DOM
处理边界抖动与精度误差
长时间运行可能出现小数坐标累积误差,导致接缝微闪:
- 对x坐标做
Math.floor()或Math.round()取整(尤其在像素级背景中) - 重置位置时,直接赋值为
targetX = Math.max(leftX, rightX) + width,而非依赖+=运算结果 - 可添加容差判断:
if (x ,避免因浮点误差错过重置时机


















