JavaScript匀速运动停止条件与抖动修复

作者:流萤

时间:2026-10-28

浏览:200

本文探讨JavaScript中匀速运动的停止逻辑。当固定速度与整数目标值不匹配时,元素会在目标点附近来回抖动。通过引入Math.abs判断距离并强制修正最终位置,可有效解决该问题,确保动画平滑停止。

文章目录

匀速运动停止条件与抖动问题分析

首先回顾之前的匀速运动代码,在修改速度speed后,会出现怎样的bug。这里增加了两个标杆用于测试。

代码如下:

<style type="text/css">
#div1 {
width: 100px;
height: 100px;
position: absolute;
background: red;
top: 50px;
left: 600px;
            }
#div2 {
width: 1px;
height: 300px;
position: absolute;
left: 300px;
top: 0;
background: black;
            }
#div3 {
width: 1px;
height: 300px;
position: absolute;
left: 100px;
top: 0;
background: black;
            }
</style>
<script type="text/javascript">
var time = null;
function startMove(iTarget) {
var oDiv = document.getElementById("div1");
clearInterval(time);
time = setInterval(function() {
var speed = 0;
if (oDiv.offsetLeft < iTarget) {
speed = 7;
} else {
speed = -7;
                    }
// 其实这种情况是有问题的
oDiv.style.left = oDiv.offsetLeft + speed + 'px';
                    
}, 30)
            }
</script>
</head>
<body>
<input type="button" id="btn" value="到100" onclick="startMove(100)" />
<input type="button" id="btn" value="到300" onclick="startMove(300)" />
<div id="div1">
</div>
<div id="div2">
</div>
<div id="div3">
</div>
</body>

抖动产生的原因

如果将速度设置为7这样的奇数,而目标点是整数,就会出现无法到达目标点或在目标点附近来回抖动的bug。

匀速运动停止条件与抖动问题分析

为什么会出现这种情况呢?

实际上,当物体到达目标点时,无法精确停在目标点上。例如目标点是100,每次移动7个单位,此时它要么超过目标点,要么未到达。

这意味着永远无法精确到达目标点,这与之前的缓冲运动有些类似。

修正后的停止逻辑

那么到底如何计算才算到达了目标点呢?

举个例子:你打车去某个地方,司机通常会在距离目的地10米或20米的地方停下来,这就视为到达。不可能要求汽车紧贴着目标点停下。

因此,程序也是一样的,只要物体与目标点之间的距离近到一定程度,就不再继续移动,即可认为已到达。

我们看下修改后的代码:

代码如下:

<script type="text/javascript">
var time = null;
function startMove(iTarget) {
 var oDiv = document.getElementById("div1");
 clearInterval(time);
 time = setInterval(function() {
 var speed = 0;
 if (oDiv.offsetLeft < iTarget) {
 speed = 7;
 } else {
 speed = -7;
 }
 if (Math.abs(iTarget - oDiv.offsetLeft) <= 7) {
 clearInterval(time);
 oDiv.style.left=iTarget+'px';
 } else {
 oDiv.style.left = oDiv.offsetLeft + speed + 'px';
 }
 
 }, 30)
 }
 </script>

代码实现与解释

解释一下:这里为什么要用 Math.abs 取绝对值呢?

理由很简单,因为速度可能是正的也可能是负的。

现在我们设定,只要目标和物体之间的距离小于等于7,就算到达。为什么是7呢?因为下一次运动的步长都不足7个单位了。此时我们可以认为它到达了目标点。

那现在问题又来了,这样写并没有精确地停在目标点的位置。所以我们加了一句简单的话,直接让left等于目标点:oDiv.style.left=iTarget+'px';

实际上最后一次走的不足7个单位,但是程序运行速度极快,人眼是看不出来的。

这个时候就没有问题了。

这个就是匀速运动的停止条件。有朋友问,为什么缓冲运动没有这么麻烦呢?

因为它的速度是变化的,越来越小,直到最后甚至只移动1个单位,一步一步前进肯定不会出现这样的问题。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章