我們先來看下之前的勻速運(yùn)動(dòng)的代碼,修改了速度 speed 后會(huì)出現(xiàn)怎么樣的一個(gè) bug。這里加了兩個(gè)標(biāo)桿用于測(cè)試。
<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;
}
// 其實(shí)這種情況是有問題的
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>
其實(shí)這樣的代碼如果把速度改成 7 這種奇數(shù),而到達(dá)目標(biāo)點(diǎn)卻是一個(gè)整數(shù),這樣就會(huì)出現(xiàn)未能達(dá)目標(biāo)點(diǎn)或超過目標(biāo)點(diǎn)來回抖動(dòng)的 bug。
http://wiki.jikexueyuan.com/project/brief-talk-js/images/5.png" alt="" />
那為什么會(huì)出現(xiàn)這種情況呢 ?
實(shí)際上來說他到達(dá)目標(biāo)點(diǎn)的時(shí)候無法精確到目標(biāo)點(diǎn),若目標(biāo)點(diǎn)是 100,每次走 7 個(gè),這個(gè)時(shí)候他要么就是過了目標(biāo)點(diǎn),要么就是沒過。
永遠(yuǎn)到不了目標(biāo)點(diǎn)。其實(shí)幫之前的緩沖有點(diǎn)像。
那么到底怎么算才是到達(dá)了目標(biāo)點(diǎn)呢?
舉個(gè)例子:你打車到某個(gè)地方,司機(jī)肯定是到哪里差不多離個(gè) 10 米 20 米就停下來了,就算到了。不可能要求汽車貼到那個(gè)地方停下來吧。
所以說呢,其實(shí)來講程序也是一樣的,我們只要物體和目標(biāo)點(diǎn)之間的距離近到一定的程度,就不需要再近了,就認(rèn)為到了。
我們看下修改后的代碼:
<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 取絕對(duì)值呢?
理由很簡(jiǎn)單,因?yàn)樗俣瓤赡苁钦目赡苁秦?fù)的。
現(xiàn)在我們讓目標(biāo)和物體之間的距離只要小于等 7, 那就算到了。為什么是 7 呢?因?yàn)樗乱淮蔚倪\(yùn)動(dòng)都不足 7 個(gè)了。這個(gè)時(shí)候我們就算他到了目標(biāo)點(diǎn)了。
那現(xiàn)在問題又來了, 這樣寫 他并沒有精確的停在目標(biāo)點(diǎn)的位置。所以我們加了一句簡(jiǎn)單的話,直接讓 left 等于目標(biāo)點(diǎn)。oDiv.style.left=iTarget+'px';
實(shí)際上最后一次走的不足 7 個(gè),但是大家都知道程序這個(gè)運(yùn)行的太快了,人眼是看不出來的。
這個(gè)時(shí)候就沒有問題了。
這個(gè)就是勻速運(yùn)動(dòng)的停止條件。 那有朋友問,為什么緩沖運(yùn)動(dòng)沒有這么麻煩呢?
因?yàn)樗乃俣仁亲兊模絹碓叫?,直到最后他甚至就到達(dá) 1 了,一步一步往前肯定不會(huì)出現(xiàn)這樣的問題。