本文,是接着上文[js高手之路]匀速运动与实例实战(侧边栏,淡入淡出)继续的,在这篇文章的最后,我们做了2个小实例:侧边栏与改变透明度的淡入淡出效果,本文我们把上文的animate函数,继续改造,让他变得更加的通用和强大:
1,支持多个物体的运动
2,同时运动
3,顺序运动
这三种运动方式也是jquery中animate函数支持的
一、animate函数中怎么区分变化不同的样式?
上文中,侧边栏效果 用的animate函数 改变的是left值
1 function animate(obj, target, speed) {
2 clearInterval(timer);
3 timer = setInterval(function () {
4 if (obj.offsetLeft == target) {
5 clearInterval(timer);
6 } else {
7 obj.style.left = obj.offsetLeft speed 'px';
8 }
9 }, 30);
10 }
淡入淡出效果 用的animate函数 改变的是透明度
1 function animate(obj, target, speed) {
2 clearInterval(timer);
3 var cur = 0;
4 timer = setInterval(function () {
5 cur = css( obj, 'opacity') * 100;
6 if( cur == target ){
7 clearInterval( timer );
8 }else {
9 cur = speed;
10 obj.style.opacity = cur / 100;
11 obj.style.filter = "alpha(opacity:" cur ")";
12 }
13 }, 30);
14 }
而我们封装的函数,要变成通用的,首先面临的问题就是 这个函数要同时支持left值和透明度的变化,更通用的做法应该是要支持所有的样式变化,比如轮播功能,他有左右滑动,也有上下滑动。
我们可以在获取样式和改变样式的时候,做一下判断就可以了,判断分2类就能达到目的,因为其他样式( margin, left, top, right, font-size等等 )都是px,而透明度没有px单位
1 function animate(obj, attr, target, speed) {
2 clearInterval(timer);
3 var cur = 0;
4 timer = setInterval(function () {
5 if (attr == 'opacity') {
6 cur = css(obj, 'opacity') * 100;
7 } else {
8 cur = parseInt(css(obj, attr));
9 }
10
11 if (cur == target) {
12 clearInterval(timer);
13 } else {
14 if (attr == 'opacity') {
15 obj.style.opacity = ( cur speed ) / 100;
16 obj.style.filter = "alpha(opacity:" (cur speed) ")";
17 } else {
18 obj.style[attr] = cur speed "px";
19 }
20 }
21 }, 30);
22 }
合并之后的animate相比之前多了一个参数attr, 这个参数就是变化的样式,obj: 变化的对象, target: 样式需要变化到的目标值. speed: 样式每次变化的大小
如:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!doctype html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>合并的运动 - by ghostwu</title>
6 <style>
7 img {
8 border: none;
9 opacity: 0.3;
10 filter: alpha(opacity:30);
11 position: absolute;
12 left: 200px;
13 }
14
15 #box {
16 width: 150px;
17 height: 300px;
18 background: red;
19 position: absolute;
20 left: -150px;
21 top: 50px;
22 }
23
24 #box div {
25 width: 28px;
26 height: 100px;
27 position: absolute;
28 right: -28px;
29 top: 100px;
30 background: green;
31 }
32 </style>
33 <script>
34 window.onload = function () {
35 var oImg = document.getElementById("img"),
36 oBox = document.getElementById("box"),
37 timer = null;
38
39 oImg.onmouseover = function () {
40 animate(this, 'opacity', 100, 10);
41 }
42 oImg.onmouseout = function () {
43 animate(this, 'opacity', 30, -10);
44 }
45
46 oBox.onmouseover = function () {
47 animate(this, 'left', 0, 10);
48 }
49
50 oBox.onmouseout = function () {
51 animate(this, 'left', -150, -10);
52 }
53
54 function animate(obj, attr, target, speed) {
55 clearInterval(timer);
56 var cur = 0;
57 timer = setInterval(function () {
58 if (attr == 'opacity') {
59 cur = css(obj, 'opacity') * 100;
60 } else {
61 cur = parseInt(css(obj, attr));
62 }
63
64 if (cur == target) {
65 clearInterval(timer);
66 } else {
67 if (attr == 'opacity') {
68 obj.style.opacity = ( cur speed ) / 100;
69 obj.style.filter = "alpha(opacity:" (cur speed) ")";
70 } else {
71 obj.style[attr] = cur speed "px";
72 }
73 }
74 }, 30);
75 }
76
77 function css(obj, attr) {
78 if (obj.currentStyle) {
79 return obj.currentStyle[attr];
80 } else {
81 return getComputedStyle(obj, false)[attr];
82 }
83 }
84 }
85 </script>
86 </head>
87 <body>
88 <div id="box">
89 <div>分享到</div>
90 </div>
91 <img src="./img/h4.jpg" alt="" id="img"/>
92 </body>
93 </html>
上述就是完整的代码实例,请自行展开,点击run code预览效果
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!doctype html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>Document</title>
6 <style>
7 img {
8 border: none;
9 opacity: 0.3;
10 filter: alpha(opacity:30);
11 position: absolute;
12 left: 200px;
13 }
14
15 #box {
16 width: 150px;
17 height: 300px;
18 background: red;
19 position: absolute;
20 left: -150px;
21 top: 50px;
22 }
23
24 #box div {
25 width: 28px;
26 height: 100px;
27 position: absolute;
28 right: -28px;
29 top: 100px;
30 background: green;
31 }
32 </style>
33 <script>
34 window.onload = function () {
35 var oImg = document.getElementById("img"),
36 oBox = document.getElementById("box");
37
38 oImg.onmouseover = function () {
39 animate(this, 'opacity', 100, 10);
40 }
41 oImg.onmouseout = function () {
42 animate(this, 'opacity', 30, -10);
43 }
44
45 oBox.onmouseover = function () {
46 animate(this, 'left', 0, 10);
47 }
48
49 oBox.onmouseout = function () {
50 animate(this, 'left', -150, -10);
51 }
52
53 function animate(obj, attr, target, speed) {
54 clearInterval(obj.timer);
55 var cur = 0;
56 obj.timer = setInterval(function () {
57 if (attr == 'opacity') {
58 cur = css(obj, 'opacity') * 100;
59 } else {
60 cur = parseInt(css(obj, attr));
61 }
62
63 if (cur == target) {
64 clearInterval(obj.timer);
65 } else {
66 if (attr == 'opacity') {
67 obj.style.opacity = ( cur speed ) / 100;
68 obj.style.filter = "alpha(opacity:" (cur speed) ")";
69 } else {
70 obj.style[attr] = cur speed "px";
71 }
72 }
73 }, 30);
74 }
75
76 function css(obj, attr) {
77 if (obj.currentStyle) {
78 return obj.currentStyle[attr];
79 } else {
80 return getComputedStyle(obj, false)[attr];
81 }
82 }
83 }
84 </script>
85 </head>
86 <body>
87 <div id="box">
88 <div>分享到</div>
89 </div>
90 <img src="./img/h4.jpg" alt="" id="img"/>
91 </body>
92 </html>
至此,我们就完成了多物体运动与不同样式的修改
二、让animate函数支持多个样式同时改变
比如:
oBox.onmouseover = function(){
animate( this, { "width" : 500, "height" : 400 }, 10 );
}
oBox是一个div元素,animate各参数的意思:
this: 当前div元素
{width : 500, "height" : 400 } : 把宽度变成500, 高度变成400,这两个样式要在同一时间完成,
10: 样式每次在原来的基础上变化10(如width初始值200--> 210, 220, 230.....)
完整的同时运动变化 代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!doctype html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>Document</title>
6 <style>
7 div {
8 width: 200px;
9 height: 200px;
10 background: red;
11 }
12 </style>
13 <script>
14 window.onload = function () {
15 var oBox = document.getElementById("box");
16 oBox.onmouseover = function(){
17 // animate( this, { "width" : 500, "height" : 500 }, 10 );
18 animate( this, { "width" : 500, "height" : 400 }, 10 );
19 }
20
21 function animate(obj, attr, speed) {
22 clearInterval(obj.timer);
23 var cur = 0;
24 obj.timer = setInterval(function () {
25 for ( var key in attr ) {
26 if (key == 'opacity') {
27 cur = css(obj, 'opacity') * 100;
28 } else {
29 cur = parseInt(css(obj, key));
30 }
31 var target = attr[key];
32 if (cur == target) {
33 clearInterval(obj.timer);
34 } else {
35 if (key == 'opacity') {
36 obj.style.opacity = ( cur speed ) / 100;
37 obj.style.filter = "alpha(opacity:" (cur speed) ")";
38 } else {
39 obj.style[key] = cur speed "px";
40 }
41 }
42 }
43 }, 30);
44 }
45
46 function css(obj, attr) {
47 if (obj.currentStyle) {
48 return obj.currentStyle[attr];
49 } else {
50 return getComputedStyle(obj, false)[attr];
51 }
52 }
53 }
54 </script>
55 </head>
56 <body>
57 <div id="box"></div>
58 </body>
59 </html>
请自行展开这段代码,这段代码能够同时运动,但是有一个问题:
div的初始宽度与高度( width : 200, height : 200)
变化步长一样( 10 )
变化时间一样( 每30毫秒变化一次 )
目标( width: 500, height : 400 )
你能想到什么问题吗?( 两个人在同一起跑线上,速度一样, 时间一样,但是要同时到达不同的目标,一个500, 一个400 )
答案是很明显的,肯定是目标近的( height : 400 )那个先到达,然后把对象上的定时器关了,另一个目标更远的( width: 500 )肯定到达不了
你可以在这句代码下面,输出当前的值和目标值:
输出来的结果是:
从上图可以看出,height已经达到了400px,但是width停在了410px,为什么不是400px ? 因为width = 400的时候, 就是( cur == 500 ) 相当于( 400 == 500 ) 不成立,所以执行了else语句,width = cur 10 = 400 10 = 410,然后height到达400px停止了定时器,所以width停在了410px.
那么我们怎么解决这个问题呢?
其实也好办,就是height = 400的时候 不要把定时器关了,应该等width = 500的时候再关闭定时器,不就在同一时间,完成了同时到达目标的效果吗?
修改后的代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!doctype html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>Document</title>
6 <style>
7 div {
8 width: 200px;
9 height: 200px;
10 background: red;
11 }
12 </style>
13 <script>
14 window.onload = function () {
15 var oBox = document.getElementById("box");
16 oBox.onmouseover = function(){
17 animate( this, { "width" : 500, "height" : 400 }, 10 );
18 }
19
20 function animate(obj, attr, speed) {
21 clearInterval(obj.timer);
22 var cur = 0;
23 obj.timer = setInterval(function () {
24 var bFlag = true;
25 for ( var key in attr ) {
26 if (key == 'opacity') {
27 cur = css(obj, 'opacity') * 100;
28 } else {
29 cur = parseInt(css(obj, key));
30 }
31 var target = attr[key];
32 if (cur != target) {
33 bFlag = false;
34 if (key == 'opacity') {
35 obj.style.opacity = ( cur speed ) / 100;
36 obj.style.filter = "alpha(opacity:" (cur speed) ")";
37 } else {
38 obj.style[key] = cur speed "px";
39 }
40 }
41 }
42 if ( bFlag ) {
43 clearInterval( obj.timer );
44 }
45 }, 30);
46 }
47
48 function css(obj, attr) {
49 if (obj.currentStyle) {
50 return obj.currentStyle[attr];
51 } else {
52 return getComputedStyle(obj, false)[attr];
53 }
54 }
55 }
56 </script>
57 </head>
58 <body>
59 <div id="box"></div>
60 </body>
61 </html>
声明一个变量,每次变化完一次( width, height )样式 把bFlag = true, 只要在for循环中有一个没有到达目标,bFlag的值都是false,这样就不会关闭定时器。当两个都到达目标,才关闭定时器.
三、顺序运动
如样式变化,按顺序来,不是同时变化, 如:
oBox.onmouseover = function(){
//回调函数: 把函数当做参数传递给另一个函数
animate( this, { 'width' : 500 }, 10, function(){
animate( this, { 'height' : 500 }, 10 );
} );
}
当把width变成500px的时候,如果传递了回调函数, 再接着执行回调函数里面的运动
修改后的完整代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!DOCTYPE html>
2 <html>
3 <head lang="en">
4 <meta charset="UTF-8">
5 <title>通用的匀速运动框架 - by ghostwu</title>
6 <style>
7 div {
8 width: 200px;
9 height: 200px;
10 background: red;
11 }
12 </style>
13 <script>
14 window.onload = function () {
15 var oBox = document.getElementById("box");
16 oBox.onmouseover = function(){
17 //回调函数: 把函数当做参数传递给另一个函数
18 animate( this, { 'width' : 500 }, 10, function(){
19 animate( this, { 'height' : 500 }, 10 );
20 } );
21 }
22
23 function animate(obj, attr, speed, fn ) {
24
25 clearInterval(obj.timer);
26 var cur = 0;
27 obj.timer = setInterval(function () {
28 var bFlag = true;
29 for (var key in attr) {
30 if (key == 'opacity') {
31 cur = css(obj, 'opacity') * 100;
32 } else {
33 cur = parseInt(css(obj, key));
34 }
35 var target = attr[key];
36 if (cur != target) {
37 bFlag = false;
38 if (key == 'opacity') {
39 obj.style.opacity = ( cur speed ) / 100;
40 obj.style.filter = "alpha(opacity:" (cur speed) ")";
41 } else {
42 obj.style[key] = cur speed "px";
43 }
44 }
45 }
46
47 if (bFlag) {
48 clearInterval(obj.timer);
49 fn && fn.call( obj );
50 }
51 }, 30);
52 }
53
54 function css(obj, attr) {
55 if (obj.currentStyle) {
56 return obj.currentStyle[attr];
57 } else {
58 return getComputedStyle(obj, false)[attr];
59 }
60 }
61 }
62 </script>
63 </head>
64 <body>
65 <div id="box"></div>
66 </body>
67 </html>