本文给大家分享的是个人在学习 js 运动动画的过程中总结的我们需要注意的 8 个知识点,分别是速度动画、透明度渐变、缓冲运动、多物体运动、获取样式、任意属性值、链式运动和同时运动,非常的详细,推荐给小伙伴们。
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
今天简单的学了一下 js 运动动画,记录一下自己的心得体会,分享给大家。
下面是我整理出来的结果。
知识点一:速度动画。
1. 首先第一步实现速度运动动画,封装一个函数,用到的知识是 setInterval(function(){
- oDiv.style.left=oDiv.offsetLeft+10+"px";
- },30).
对于这里为什么要用到 offsetLeft,我特意百度了一下,我得到的有用信息是:
a.offsetLeft 和 left 的相同之处都是表示子节点相对于父节点的左位置。
b. 但是 left 是既可以读又可以写的,而 offsetLeft 是只读的;
c. 并且 offsetLeft 是没有单位的,获取子节点位置的时候后面不带 px。
这里在引申一下其他的知识,感谢这位博主,{aa0aa}。
2. 让运动的节点停止下来,这里我们用 if 语句做一个验证,如果 offsetLeft==0,clearInterval(timer),这里的 timer 应该事先初始化 = null,然后将之前的那个运动动画赋值给它。
3. 这里有一个问题,如果在运动结束之前再次触发的运动,那么运动的速度会累加,这里,只要在整个运动开始之前,clearInterval(timer)就可以了。
4. 设置移入移除效果,给运动设置参数,一个是速度 speed,一个是目标位置 iTarget,我们发现速度也是可以通过 ITarget 的位置来判断的,所以只需要一个参数即可。
知识点二:透明度渐变
1. 其实,跟刚刚是差不多的,只不过 ITarget 的值为透明度而已,流程还是清除定时器再开一个定时器判断等等。
2. 定义一个参数 alpha = 透明度,注意定时器里面应该这样写:
- alpha+=speed;
- oDiv.style.filter='alpha(opacity:'+alpha+')'; //这是非常重要的一种方法,注意是这样写的
- oDiv.style.opacity=alpha/100; //注意不要忘记除以100
3. 以上都是行内样式。
知识点三:缓冲运动
1. 缓冲运动就是距离越大,速度就愈大,距离越小,速度就越小,即速度与距离有关。
2. 根据上面的说法,对速度进行重新的定义,一开始速度为 0,而现在:
- var speed=iTarget-oDiv.offsetLeft;
重新定义定时器:
- oDiv.style.left=oDiv.offsetLeft+speed+'px';
此时我们发现速度太大了,可以这样:
- var speed=(iTarget-oDiv.offsetLeft)/10;
3. 此时会有一个严重的问题,因为屏幕的最小单位为 px,所以会出现最终的 left 值为小数,而不为目标的 iTarget, 可以通过判断来解决,这里要引入 Math.floor(),这是向下取整,同样还有 Math.ceil(),这是向上取整。在定义 speed 后我们这样写:
- speed=speed>0?Math.ceil(speed):Math.floor(speed);
这样就可以完全保证速度都是整数,并且在临界值上都为 0。
知识点四:多物体运动
1. 先获取所有的物体,形成一个数组,然后再用 for 循环来做(这种方法多么经典呀!),在 for 循环中添加节点事件,在函数中可以用 this 代替当前的节点,eg:startMove(this,iTarget), 定义函数时 startMove(obj,iTarget).
2. 取当前宽度 offsetWidth 的时候就要用 obj 的值了。
3. 当鼠标移动特别快的时候,节点的宽度未能恢复原状,这是因为定时器是大家公用的定时器,上一个节点还未恢复原状下一个节点就已经清除定时器了,解决的办法就是给每一个节点加一个 index,就是在上面的 for 循环中加上 aDiv[i].timer=null; 然后再定义函数中用 obj.timer 替换 timer。由此我们要注意共用定时器会出事的。
4. 透明度的运动中,alpha 代替了 speed,但是即使定时器不共用,多物体的运动也会出现问题,这是因为 alpha 公用的原因,导致各物体相互撕扯,解决办法就是可以像 timer 那样在 for 循环中给每个节点都分配 alpha。
总结:解决冲突问题,要么初始化,要么个性化。
知识点五. 获取样式
1. 在改变节点宽度(移入大,移除小)的定时器中,如果给节点添加一个 border 边框,那么在移入的时候比目标节点小,移出的时候比目标节点大。注意 width+padding+scrollbar(滚动条)+border,所以原因就是每次 offset 都会增加 border*2-(定时器中每次减少的数值)。
2. 解决以上问题的办法就是在行内写入 width,并且使用 parseInt(oDiv.style.width) 代替 offsetLeft,但是并不能总是写在行内,所以我们定义一个函数,获取链入样式:
- function getStyle(obj, attr) {
- if (obj.currentStyle) {
- return obj.currentStyle[attr]; //ie浏览器
- }
- else {
- return getComputerStyle(obj, false)[attr]; //其他浏览器
- }
- }
3. 对于 font-size 这种,在 js 里只有 fontSize 这一种写法。
知识点六:任意属性值
1. 所有的 offset - 的都会有小 bug,要用 getStyle 函数,这个函数经常和 parseInt()一起用,并通常用变量保存。
2. 在写 style.width 的时候,也可以写成 style['width']。
3. 对于多物体的属性值调整,可以将样式作为参数封装一下,这样多物体属性的函数就包括了(obj,attr,iTarget)这三个属性值。
4. 以上的这个运动框架是不适合于透明度变化的,因为透明度都是小数的,因为两个原因,第一是 parseInt,第二是 attr=...+px,这里我们可以用一个 if 判读来对透明度进行单独处理,将 parseInt 换成 parseFloat,去掉 px。
5. 计算机本身是有一个 bug 的,0.07*100 并不等于 7,所以我们引入一个函数是 Math.round(),这是一个四舍五入的值。
知识点七:链式运动
1. 引入 move.js 框架。
2. 传入一个回调函数 fn(),用 if 判断,如果有 fn(),那么执行 fn()。
知识点八:同时运动
1. 如果写两个运动函数来控制同时运动,会发生函数覆盖。
2. 使用 json 这个知识点,json 的循环是使用 for(i in json),运动函数的参数为 obj,json,fn。
3. 没有 iTarget 这个值了,取而代之的是 json[attr].
来源: