运动原理:
对于javascript的运动简单的来说就是利用定时器让物体运动起来,并不断的改变物体的样式。在运动中我们一般改变的是物体的定位而不是margin值,因为改变margin值有时会影响其他元素容易造成页面的混乱。也许有的朋友会说难道不能使用for循环吗?其实是可以的不过for循环太快了,通常你一打开网页运动就完成了,所以我们一般使用定时器来管理运动。
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script>
window.onload=function(){
var oT=document.getElementsByTagName('textarea')[0];
var oBtn=document.getElementsByTagName('input')[0];
var oTime=new Date().getTime();//开定时器前先获取一个时间戳
var timer=setInterval(function(){
var oTime2=new Date().getTime();//根据定时器的间隔时间再获取一个时间戳
oT.innerHTML+=oTime2-oTime+'\n';//在文本区域内显示时间差值
oTime=oTime2;//对初始时间戳重新赋值
},1)
oBtn.onclick=function(){ //暂停键
clearInterval(timer);
};
};
</script>
</head>
<body>
<textarea rows="" cols="" id="t1"></textarea>
<input type="button" name="" value="btn">
</body>
</html>
希望各位小伙伴可以在编辑器试一下该段代码。
在该段代码中显示出一个问题,就是定时器的时间间隔并不是太稳定
(ps:你们也看到了飘得很是厉害。。。。)
在javascript的定时器中选取间隔数字是有讲究的,一般选择的运动时间间隔为20-40ms之间,我们平均一下选取30ms。一来人类视觉感受可以接受,时间间隔长会产生钝感,时间间隔太短的话会对性能的消耗也很大(碰到个辣眼睛的图片会晃瞎哈哈哈)。我们选取30ms如下图:
小伙伴们看到了吧,很稳定吧。
对于定时器在javascript中的运行顺序也需要提一下,计算机在执行代码时会先执行定时器下边的代码,到了时间才会执行定时器里边的。
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script>
var n=1;
setInterval(function(){
n=2;
},1);
alert(n);
</script>
</head>
<body>
</body>
</html>
该代码显示的结果为1。
定时器还有一个问题就是当你在浏览器中打开另外一个页面时浏览器会默认的将你的原来有定时器的那个页面的时间间隔降为1s以优化性能。
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script>
var n=0;
setInterval(function(){
n++;
document.title=n;
},1);
</script>
</head>
<body>
</body>
</html>
接下来我们可以试一下物体的运动了。
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
*{margin: 0;
padding: 0;
list-style: none;}
div{width: 100px;
height: 100px;
background: red;
position: absolute;
left: 0;}
</style>
<script>
window.onload=function(){
var oDiv=document.getElementsByTagName('div')[0];
var time=1000;//总时间;
var start=0;//开始
var end=300;//结束
var dis=end-start;//总位置
var count=Math.ceil(time/30);//次数
var n=0;//统计步数;
var timer=null;
timer=setInterval(function(){
n++;
oDiv.style.left=n*dis/count+'px';//n*一步距离;
oDiv.style.top=n*dis/count+'px';//n*一步距离;
if(n==count){
clearInterval(timer);
}
},30);
}
</script>
</head>
<body>
<div></div>
</body>
</html>
在以上代码我们首先要设定好的就是总时间、开始位置、目标位置、总路程、多长时间走一步(其实就是定时器设置的时间)、一共走多少步count(总时间除以设置时间: time/设置时间。其中取整有几种方式:parseInt\Math.floor()\Math.ceil()\Math.round() )、一步走多远:dis/count。
在完成以上目标后我们可以继续加一些别的东西,比如将以上的代码进行封装。
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
*{margin: 0;
padding: 0;
list-style: none;}
div{width: 100px;
height: 100px;
background: red;
position: absolute;
left: 100px;
top: 0;}
</style>
<script>
function move(obj,end){
var time=1000;//总时间;
var start=obj.offsetLeft;//开始(在这里初试位置为left:100px)
//注销var end=300;//结束
var dis=end-start;//总位置
var count=Math.ceil(time/30);//次数
var n=0;//统计步数;
var timer=null;
timer=setInterval(function(){
n++;
obj.style.left=start+n*dis/count+'px';//n*一步距离;
if(n==count){
clearInterval(timer);
}
},30);
}
window.onload=function(){
var oDiv=document.getElementsByTagName('div')[0];
move(oDiv,300);
}
</script>
</head>
<body>
<div></div>
</body>
</html>
以上的代码除了封装以外,还改变的物体运动的初始位置,各位小伙伴可以敲敲感受一下。此外我们还可以加上透明度。
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
div {
width: 100px;
height: 100px;
background: red;
position: absolute;
left: 100px;
top: 0;
}
</style>
<script>
function getStyle(obj,sName){
return (obj.currentStyle||getComputedStyle(obj,false))[sName]
}
function move(obj, sName,end) {
var time = 1000; //总时间;
var star = parseFloat(getStyle(obj,sName)); //这里用parseFloat取整
//注销var end=300;//结束
var dis = end - star; //总位置
var count = Math.ceil(time / 30); //次数
var n = 0; //统计步数;
var timer = null;
timer = setInterval(function () {
n++;
if(sName=='opacity'){
obj.style[sName] = star + n * dis / count ;
}else{
obj.style[sName] = star + n * dis / count + 'px'; //n*一步距离;
}
if (n == count) {
clearInterval(timer);
}
}, 30);
}
window.onload = function () {
var oDiv = document.getElementsByTagName('div')[0];
move(oDiv,'opacity', 0);
}
</script>
</head>
<body>
<div></div>
</body>
</html>
此为单物体运动,如果多物体还这样的话就会出现错误。在定时器中还有一个问题就是*一定要保证一个物体上有只一个定时器(定时器加载到物体身上以达到互相独立)。
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
li{width: 100px;
height: 50px;
background:#6cf;
margin-bottom: 10px;
}
</style>
<script>
function getStyle(obj,sName){
return (obj.currentStyle||getComputedStyle(obj,false))[sName]
}
function move(obj, sName,end) {
var time = 1000; //总时间;
var start = parseFloat(getStyle(obj,sName)); //这里用parseFloat取整
//注销var end=300;//结束
var dis = end - start; //总位置
var count = Math.ceil(time / 30); //次数
var n = 0; //统计步数;
clearInterval(obj.timer);
obj.timer = setInterval(function () {
n++;
if(sName=='opacity'){
obj.style[sName] = start + n * dis / count ;
}else{
obj.style[sName] = start + n * dis / count + 'px'; //n*一步距离;
}
if (n == count) {
clearInterval(obj.timer);
}
}, 30);
}
window.onload = function () {
var aLi = document.getElementsByTagName('li');
for(var i=0;i<aLi.length;i++){
aLi[i].onmouseover=function(){
move(this,'width',400);
}
aLi[i].onmouseout=function(){
move(this,'width',100);
}
}
}
</script>
</head>
<body>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</body>
</html>
千万记住要清定时器。。否则他会一直动哈哈。而且事件之间也会起冲突。
大家肯定对于上边那个关于透明度的问题有疑问,我除了设定透明度还要设置宽度怎么办呢,原来的数据被透明度给占据了。这里就由json出场了。将相对应的需要获取的键值加入for in循环
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
div {
width: 100px;
height: 100px;
background: red;
position: absolute;
left: 100px;
top: 0;
}
</style>
<script>
function getStyle(obj, sName) {
return (obj.currentStyle || getComputedStyle(obj, false))[sName]
}
//function move(obj, sName,end) {原来的替换为下边这个
function move(obj, json) {
var time = 1000; //总时间;
var start = {} //{width:0;height:0;}开始位置{left:0,top:0}
var dis = {} //{width:300;height:300;}总距离{left:300,top:300}
for (var name in json) {
start[name] = parseFloat(getStyle(obj, name)); //
dis[name] = json[name] - start[name];
console.log(start);
console.log(dis)
}
var count = Math.ceil(time / 30); //次数
var n = 0; //统计步数;
clearInterval(obj.timer);
obj.timer = setInterval(function () {
n++;
for (var name in json) {
if (name == 'opacity') {
obj.style[name] = start[name] + n * dis[name] / count;
} else {
obj.style[name] = start[name] + n * dis[name] / count + 'px'; //n*一步距离;
}
}
if (n == count) {
clearInterval(obj.timer);
}
}, 30);
}
window.onload = function () {
var oDiv = document.getElementsByTagName('div')[0];
document.onclick = function () {
move(oDiv, {
'width': 300,
'height': 300,
'opacity': 0
});
};
}
</script>
</head>
<body>
<div></div>
</body>
</html>
已经为大家加入了console.log大家可以看一下start与end的json的键值对。
在此基础上我们可以进一步升级,加入控制时间选项。
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
div {
width: 100px;
height: 100px;
background: red;
position: absolute;
left: 100px;
top: 0;
}
</style>
<script>
function getStyle(obj, sName) {
return (obj.currentStyle || getComputedStyle(obj, false))[sName]
}
//function move(obj, sName,end) {
function move(obj, json,duration,complete) {
var time=duration||1000;//前者条件满足就不往后走了,或的条件
var start = {} //{width:0;height:0;}开始位置{left:0,top:0}
var dis = {} //{width:300;height:300;}总距离{left:300,top:300}
for (var name in json) {
start[name] = parseFloat(getStyle(obj, name)); //
dis[name] = json[name] - start[name];
// console.log(start);
// console.log(dis)
}
var count = Math.ceil(time / 30); //次数
var n = 0; //统计步数;
clearInterval(obj.timer);
obj.timer = setInterval(function () {
n++;
for (var name in json) {
if (name == 'opacity') {
obj.style[name] = start[name] + n * dis[name] / count;
} else {
obj.style[name] = start[name] + n * dis[name] / count + 'px'; //n*一步距离;
}
}
if (n == count) {
clearInterval(obj.timer);
complete && complete();//如果有就执行如果没有就不执行,防止了无函数出现undefine。
}
}, 30);
}
window.onload = function () {
var oDiv = document.getElementsByTagName('div')[0];
document.onclick = function () {
move(oDiv, {
'width': 300,
'height': 300,
'opacity': 0
},3000,function(){
alert(1);
});
};
}
</script>
</head>
<body>
<div></div>
</body>
</html>
我们将控制时间与完成时执行事件封装。
示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
div {
width: 100px;
height: 100px;
background: red;
position: absolute;
left: 100px;
top: 0;
}
</style>
<script>
function getStyle(obj, sName) {
return (obj.currentStyle || getComputedStyle(obj, false))[sName]
}
//function move(obj, sName,end) {
function move(obj, json,options) {
//var time = 1000; //总时间;
var options=options||{};
var time=options.duration||1000;//前者条件满足就不往后走了,或的条件
var start = {} //{width:0;height:0;}开始位置{left:0,top:0}
var dis = {} //{width:300;height:300;}总距离{left:300,top:300}
for (var name in json) {
start[name] = parseFloat(getStyle(obj, name)); //
dis[name] = json[name] - start[name];
// console.log(start);
// console.log(dis)
}
var count = Math.ceil(time / 30); //次数
var n = 0; //统计步数;
clearInterval(obj.timer);
obj.timer = setInterval(function () {
n++;
for (var name in json) {
if (name == 'opacity') {
obj.style[name] = start[name] + n * dis[name] / count;
} else {
obj.style[name] = start[name] + n * dis[name] / count + 'px'; //n*一步距离;
}
}
if (n == count) {
clearInterval(obj.timer);
options.complete && options.complete();//如果有就执行如果没有就不执行,防止了无函数出现undefine。
}
}, 30);
}
window.onload = function () {
var oDiv = document.getElementsByTagName('div')[0];
document.onclick = function () {
move(oDiv, {
"width": 300,
"height": 300,
"opacity": 0
},{"duration":3000,"complete":function(){
alert(1);
}});
};
}
</script>
</head>
<body>
<div></div>
</body>
</html>
到这里对于运动方面就告一段落了,在工作中我们都会使用已经封装好的框架来用,以上内容就是为了更好的理解javascript运动的逻辑问题。
本人前端小白,希望在自己努力的同时可以认识更多志同道合的朋友,也希望大神和老师傅们能够提携一二带我上车,本人不胜感激。哈哈,希望小伙伴们能够给出意见,让我能够加以改正,谢谢!