1. 运动基础
让Div运动起来
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style> #div1{width: 200px; height: 200px; background: red; position: absolute; top: 50px; left: 0;} </style>
<script> function startMove() { var oDiv = document.getElementById("div1"); setInterval(function(){ var speed = 10; oDiv.style.left = oDiv.offsetLeft + speed + 'px'; }, 30); } </script>
</head>
<body>
<input id="btn1" type="button" value="开始移动" onclick="startMove()" />
<div id="div1"></div>
</body>
</html>
速度——物体运动的快慢
修改speed的值,越大运动越快
运动中的Bug
- 不会停止
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style> #div1{width: 200px; height: 200px; background: red; position: absolute; top: 50px; left: 0;} </style>
<script> var timer = null; function startMove() { var oDiv = document.getElementById("div1"); timer = setInterval(function(){ var speed = 10; if(oDiv.offsetLeft == 300) { clearInterval(timer); } oDiv.style.left = oDiv.offsetLeft + speed + 'px'; }, 30); } </script>
</head>
<body>
<input id="btn1" type="button" value="开始移动" onclick="startMove()" />
<div id="div1"></div>
</body>
</html>
- 速度取某些值会无法停止
比如,当speed=7时, 将无法停止,因为oDiv.style.left的值:0,7,14,。。。,280,287,294,301,308,,,。所以offsetLeft的值不会等于300,也就不会停止。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style> #div1{width: 200px; height: 200px; background: red; position: absolute; top: 50px; left: 0;} </style>
<script> var timer = null; function startMove() { var oDiv = document.getElementById("div1"); timer = setInterval(function(){ var speed = 10; if(oDiv.offsetLeft >= 300) // 改为>= { clearInterval(timer); } oDiv.style.left = oDiv.offsetLeft + speed + 'px'; }, 30); } </script>
</head>
<body>
<input id="btn1" type="button" value="开始移动" onclick="startMove()" />
<div id="div1"></div>
</body>
</html>
- 到达位置后再点击还会运动
当div停住以后,点击按钮后div还会动一下,这是因为定时器要到下一次才会关闭,但当前的oDiv.style.left = oDiv.offsetLeft + speed + ‘px’;还是会执行一次。
解决办法:将该语句放到else里。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style> #div1{width: 200px; height: 200px; background: red; position: absolute; top: 50px; left: 0;} </style>
<script> var timer = null; function startMove() { var oDiv = document.getElementById("div1"); timer = setInterval(function(){ var speed = 10; if(oDiv.offsetLeft >= 300) { clearInterval(timer); } else { oDiv.style.left = oDiv.offsetLeft + speed + 'px'; } }, 30); } </script>
</head>
<body>
<input id="btn1" type="button" value="开始移动" onclick="startMove()" />
<div id="div1"></div>
</body>
</html>
- 重复点击速度加快
当多次点击按钮时,div移动速度加快,因为相当于开了多个定时器。
解决方法:保证每次只有一个定时器工作。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style> #div1{width: 200px; height: 200px; background: red; position: absolute; top: 50px; left: 0;} </style>
<script> var timer = null; function startMove() { var oDiv = document.getElementById("div1"); clearInterval(timer); //将其它定时器关掉! timer = setInterval(function(){ var speed = 10; if(oDiv.offsetLeft >= 300) { clearInterval(timer); } else { oDiv.style.left = oDiv.offsetLeft + speed + 'px'; } }, 30); } </script>
</head>
<body>
<input id="btn1" type="button" value="开始移动" onclick="startMove()" />
<div id="div1"></div>
</body>
</html>
2. 匀速运动
速度不变
3. 运动框架
在开始运动时,关闭已有定时器
把运动和停止隔开(if/else):运动指到达指定位置前,而停止是到达指定位置后,所以这两部分不应该同时执行,要分开。
4. 运动框架实例
例子1:“分享到”侧边栏
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style> #div1 {width: 150px; height: 200px; background: green; position: absolute; left: -150px;} #div1 span {width: 20px; height: 60px; background: blue; position: absolute; right: -20px; top: 70px;} </style>
<script> window.onclick = function () { var oDiv = document.getElementById("div1"); oDiv.onmouseover = function () { startMove(10, 0); }; oDiv.onmouseout = function () { startMove(-10, -150); }; }; var timer = null; function startMove (speed, iTarget) { var oDiv = document.getElementById("div1"); clearInterval(timer); timer = setInterval(function (){ if(oDiv.offsetLeft == iTarget) { clearInterval(timer); } else { oDiv.style.left = oDiv.offsetLeft+speed+'px'; } }, 30); } </script>
</head>
<body>
<div id="div1">
<span>分享到</span>
</div>
</body>
</html>
通过目标点,计算速度值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style> #div1 {width: 150px; height: 200px; background: green; position: absolute; left: -150px;} #div1 span {width: 20px; height: 60px; background: blue; position: absolute; right: -20px; top: 70px;} </style>
<script> window.onclick = function () { var oDiv = document.getElementById("div1"); oDiv.onmouseover = function () { startMove(0); }; oDiv.onmouseout = function () { startMove(-150); }; }; var timer = null; function startMove (iTarget) { var oDiv = document.getElementById("div1"); clearInterval(timer); //不能忘记!!! timer = setInterval(function (){ var speed = 0; //***************************** if(oDiv.offsetLeft>iTarget) { speed = -10; } else { speed = 10; } //***************************** if(oDiv.offsetLeft == iTarget) { clearInterval(timer); } else { oDiv.style.left = oDiv.offsetLeft+speed+'px'; } }, 30); } </script>
</head>
<body>
<div id="div1">
<span>分享到</span>
</div>
</body>
</html>
例子2:淡入淡出的图片
用变量存储透明度 (var alpha = 30;)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css"> #div1 {width: 200px; height: 200px; background: red; filter:alpha(opacity=30); opacity: 0.3; } </style>
<script type="text/javascript"> window.onload = function () { var oDiv = document.getElementById("div1"); oDiv.onmouseover = function () { startMove(100); }; oDiv.onmouseout = function () { startMove(30); }; }; timer = null; var alpha = 30; //用变量存储透明度 function startMove(iTarget) { var oDiv = document.getElementById("div1"); clearInterval(timer); timer = setInterval(function (){ var speed = 0; if(alpha<iTarget) { speed = 10; } else { speed = -10; } if(alpha == iTarget) { clearInterval(timer); } else { alpha += speed; oDiv.style.filter = "alpha(opacity="+alpha+")"; oDiv.style.opacity = alpha/100; } }, 30); } </script>
</head>
<body>
<div id="div1"></div>
</body>
</html>
5. 缓冲运动
逐渐变慢,最后停止 (当距离终点越远,速度越大,即速度与距离成正比。)
- 速度由距离决定
- 速度 = (目标值-当前值)/缩放系数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style> #div1{width: 100px; height: 100px; background: red; position: absolute; top: 50px; left: 0;} </style>
<script> function startMove() { var oDiv = document.getElementById("div1"); setInterval(function(){ var speed = (300-oDiv.offsetLeft)/10; oDiv.style.left = oDiv.offsetLeft + speed + 'px'; }, 30); } </script>
</head>
<body>
<input id="btn1" type="button" value="开始移动" onclick="startMove()" />
<div id="div1"></div>
</body>
</html>
例子:缓冲菜单
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style> #div1 { width: 100px; height: 100px; background: red; position: absolute; top: 50px; left: 0; } #div2 { width: 1px; height: 300px; background: black; position: absolute; top: 0; left: 300px; } </style>
<script> function startMove() { var oDiv = document.getElementById("div1"); setInterval(function(){ var speed = (300-oDiv.offsetLeft)/10; oDiv.style.left = oDiv.offsetLeft + speed + 'px'; document.title = oDiv.offsetLeft+", "+speed; }, 30); } </script>
</head>
<body>
<input id="btn1" type="button" value="开始移动" onclick="startMove()" />
<div id="div1"></div>
<div id="div2"></div>
</body>
</html>
- Bug:速度取整
setInterval(function(){
var speed = (300-oDiv.offsetLeft)/10;
speed = Math.ceil(speed); // 向上取整
oDiv.style.left = oDiv.offsetLeft + speed + 'px';
document.title = oDiv.offsetLeft+", "+speed;
}, 30);
当div从右向左运动时,用ceil取整又会出现问题,而应该用floor取整,因此,修改如下:
function startMove() {
var oDiv = document.getElementById("div1");
setInterval(function(){
var speed = (300-oDiv.offsetLeft)/10;
//speed = Math.ceil(speed); // 向上取整
speed = (speed>0) ? Math.ceil(speed) : Math.floor(speed);
oDiv.style.left = oDiv.offsetLeft + speed + 'px';
document.title = oDiv.offsetLeft+", "+speed;
}, 30);
}
注意: 凡是用到缓冲运动时,一定不能忘了取整!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style> #div1 { width: 100px; height: 100px; background: red; position: absolute; right: 0; bottom: 0; } </style>
<script> window.onscroll = function (){ var oDiv = document.getElementById("div1"); var scrollTop = document.documentElement.scrollTop||document.body.scrollTop; //改变滚动条位置时,使div始终显示在浏览器的右下角 oDiv.style.top = document.documentElement.clientHeight - oDiv.offsetHeight + scrollTop + "px"; }; </script>
</head>
<body style="height: 2000px">
<div id="div1"></div>
</body>
</html>
上面这种方法实现的侧边栏当滚动条移动很快时会跳动。
- 跟随页面滚动的缓冲侧边栏
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style> #div1 { width: 100px; height: 100px; background: red; position: absolute; right: 0; bottom: 0; } </style>
<script> window.onscroll = function (){ var oDiv = document.getElementById("div1"); var scrollTop = document.documentElement.scrollTop||document.body.scrollTop; //改变滚动条位置时,使div始终显示在浏览器的右下角 //oDiv.style.top = document.documentElement.clientHeight - oDiv.offsetHeight + scrollTop + "px"; startMove(document.documentElement.clientHeight - oDiv.offsetHeight + scrollTop ); }; var timer = null; function startMove (iTarget){ var oDiv = document.getElementById("div1"); clearInterval(timer); timer = setInterval(function (){ var speed = (iTarget-oDiv.offsetTop)/5; speed = speed>0 ? Math.ceil(speed) : Math.floor(speed); if(oDiv.offsetTop == iTarget) { clearInterval(timer); } else { oDiv.style.top = oDiv.offsetTop + speed + "px"; } }, 30); } </script>
</head>
<body style="height: 2000px">
<div id="div1"></div>
</body>
</html>
- 潜在问题:目标值不是整数时
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style> #div1 { width: 100px; height: 100px; background: red; position: absolute; right: 0; bottom: 0; } </style>
<script> window.onscroll = function (){ var oDiv = document.getElementById("div1"); var scrollTop = document.documentElement.scrollTop||document.body.scrollTop; //oDiv.style.top = (document.documentElement.clientHeight - oDiv.offsetHeight)/2 + scrollTop + "px"; startMove((document.documentElement.clientHeight - oDiv.offsetHeight)/2 + scrollTop ); }; var timer = null; function startMove (iTarget){ var oDiv = document.getElementById("div1"); clearInterval(timer); timer = setInterval(function (){ var speed = (iTarget-oDiv.offsetTop)/5; speed = speed>0 ? Math.ceil(speed) : Math.floor(speed); if(oDiv.offsetTop == iTarget) { clearInterval(timer); } else { oDiv.style.top = oDiv.offsetTop + speed + "px"; document.getElementById("txt1").value = oDiv.style.top; document.title = iTarget; } }, 30); } </script>
</head>
<body style="height: 2000px">
<div id="div1"></div>
<input id="txt1" type="text" style="position:fixed; right: 0; top: 0;"/>
</body>
</html>
div会在中间位置抖动,因为div的top值在487和488之间变换。
修改如下:
startMove(parseInt((document.documentElement.clientHeight - oDiv.offsetHeight)/2 + scrollTop ));
};
运动终止条件
匀速运动:距离足够近
例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style> #div1 { width: 100px; height: 100px; background: red; position: absolute; top: 50px; left: 600px; } #div2 { width: 1px; height: 300px; background: black; position: absolute; top: 0; left: 100px; } #div3 { width: 1px; height: 300px; background: black; position: absolute; top: 0; left: 300px; } </style>
<script> var timer = null; function startMove(iTarget) { var oDiv = document.getElementById("div1"); clearInterval(timer); setInterval(function(){ var speed = 0; if(oDiv.offsetLeft<iTarget) { speed = 7; } else { speed = -7; } if(oDiv.offsetLeft == iTarget) { clearInterval(timer); } else { oDiv.style.left = oDiv.offsetLeft + speed + 'px'; } }, 30); } </script>
</head>
<body>
<input type="button" value="移动到100" onclick="startMove(100)" />
<input type="button" value="移动到300" onclick="startMove(300)" />
<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
</body>
</html>
以上这种情况下,div停不下来,修改如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style> #div1 { width: 100px; height: 100px; background: red; position: absolute; top: 50px; left: 600px; } #div2 { width: 1px; height: 300px; background: black; position: absolute; top: 0; left: 100px; } #div3 { width: 1px; height: 300px; background: black; position: absolute; top: 0; left: 300px; } </style>
<script> var timer = null; function startMove(iTarget) { var oDiv = document.getElementById("div1"); clearInterval(timer); timer = setInterval(function(){ var speed = 0; if(oDiv.offsetLeft<iTarget) { speed = 7; } else { speed = -7; } //if(oDiv.offsetLeft == iTarget) if(Math.abs(oDiv.offsetLeft - iTarget) <= 7) { clearInterval(timer); oDiv.style.left = iTarget + "px"; } else { oDiv.style.left = oDiv.offsetLeft + speed + 'px'; } }, 30); } </script>
</head>
<body>
<input type="button" value="移动到100" onclick="startMove(100)" />
<input type="button" value="移动到300" onclick="startMove(300)" />
<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
</body>
</html>
缓冲运动:两点重合