效果描述:
做一个简单的动画效果,刚刷新页面时,SpongeBob在页面的左上角位置,随着时间推移,他匀速向右移动,直到右侧抵达页面右侧停下来。
分析:
SpongeBob作为一张图片被存放在<img>里面,<img>又被存放在<div>里面。
图片运动的本质:盒子的位移变化
只变化一次还不够,因此需要setInterval这个定时器
位移,读取时使用offsetLeft属性,赋值时使用style.left属性
注意:
1. 前者无单位,后者有
2. 只有对于具有定位属性的元素,left属性才有意义
即,存放图片的div元素必须要加
position: absolute;
当然relative也能动起来,但是一般是父元素相对定位,子元素绝对定位
停下来的本质:清除定时器
JS代码
var div = document.querySelector('div');var inter = setInterval(callback,100);function callback(){if(div.offsetLeft>1500-div.clientWidth)clearInterval(inter);div.style.left = div.offsetLeft+10+'px';}
那么,如果海绵宝宝的朋友派大星,章鱼哥也来了,是不是每个海洋生物都要重写一次上面的代码?
这时候可以选择把动画效果封装成一个函数moveRight(obj,speed),那个对象要移动,直接调用就可以了,参数1存放对象,参数2存放setInterval的间隔,值越大,移动速度越慢。
function moveRight(obj,speed){var inter = setInterval(callback,speed);function callback(){if(obj.offsetLeft>1500-obj.clientWidth)clearInterval(inter);obj.style.left = obj.offsetLeft+10+'px';} }moveRight(div,10);
但是如果每一次有一个新成员要移动,都要申请一个变量inter来存放定时器,会开辟大量的内存空间。这时候可以利用每个对象自带属性这个特征,来命名各自的定时器,即 将var inter 改成obj.inter
function moveRight(obj,speed){obj.inter = setInterval(callback,speed);function callback(){if(obj.offsetLeft>1500-obj.clientWidth)clearInterval(obj.inter);obj.style.left = obj.offsetLeft+10+'px';} }
现在再回头来开,一刷新页面元素就开始移动是很奇怪的。也就是说动画一般都会有一个触发事件。问题来了,如果某个元素的触发时间多次发生,岂不是开启了多个定时器?
答案是肯定的,对于这里封装的动画函数来说,开启多个定时器直接造成的结果就是海洋生物会移动得非常之快。如何解决?
其实只要保证定时器的唯一性即可,可以在函数的开头加上这么一句
clearInterval(obj.timer);