本文,是接着上文[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: 样式每次变化的大小

如:

oImg.onmouseover = function () {
animate(this, 'opacity', 100, 10);
}
oImg是获取到的图片对象. 这里各参数意思如下:
this:当前图片对象
opacity: 变化的样式是透明度
100: 鼠标移到图片上时,透明度变成100
10: 透明度每次在原来的基础上加10

 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>

View Code

上述就是完整的代码实例,请自行展开,点击run code预览效果

<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> img { border: none; opacity: 0.3; filter: alpha(opacity:30); position: absolute; left: 200px; } #box { width: 150px; height: 300px; background: red; position: absolute; left: -150px; top: 50px; } #box div { width: 28px; height: 100px; position: absolute; right: -28px; top: 100px; background: green; } </style> <script> window.onload = function () { var oImg = document.getElementById("img"), oBox = document.getElementById("box"), timer = null; oImg.onmouseover = function () { animate(this, 'opacity', 100, 10); } oImg.onmouseout = function () { animate(this, 'opacity', 30, -10); } oBox.onmouseover = function () { animate(this, 'left', 0, 10); } oBox.onmouseout = function () { animate(this, 'left', -150, -10); } function animate(obj, attr, target, speed) { clearInterval(timer); var cur = 0; timer = setInterval(function () { if (attr == 'opacity') { cur = css(obj, 'opacity') * 100; } else { cur = parseInt(css(obj, attr)); } if (cur == target) { clearInterval(timer); } else { if (attr == 'opacity') { obj.style.opacity = ( cur + speed ) / 100; obj.style.filter = "alpha(opacity:" + (cur + speed) + ")"; } else { obj.style[attr] = cur + speed + "px"; } } }, 30); } function css(obj, attr) { if (obj.currentStyle) { return obj.currentStyle[attr]; } else { return getComputedStyle(obj, false)[attr]; } } } </script> </head> <body> <div id="box"> <div>分享到</div> </div> <img src="http://images2017.cnblogs.com/blog/253192/201710/253192-20171015095909480-1867777993.png" alt="" id="img"/> </body> </html>
run code
当你分别测试这两个功能的时候:
移动到图片上然后移出来
移动到分享到,然后移出来
这样是没有问题的
如果你这样测试:
移动到 分享到,然后迅速又移动到图片上, 这个时候你会发现 分享到 停下来了,这就不符合逻辑了! 按道理来说,鼠标移动到图片上,相当于触发了 “分享到” 的mouseout( 鼠标移出事件 ),那么  "分享到" 这个时候要隐藏,并不是停止。 为什么会这样呢?因为这两个运动共享了一个定时器,当鼠标移动到图片上,开启定时器的时候,把“分享到”的定时器给停了。那么再做多物体运动的时候,我们就要把定时器拆分,每个对象都要有一个定时器,怎么做呢? 非常简单,不要定义一个简单的timer变量,我们只要把timer加在obj对象上,那么每个对象都有一个timer属性,就达到定时器的分离效果了
修改之后的完整代码如下,请自行展开:

 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>

View Code

至此,我们就完成了多物体运动与不同样式的修改

二、让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.....)

完整的同时运动变化 代码:

 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>

View Code

请自行展开这段代码,这段代码能够同时运动,但是有一个问题:

div的初始宽度与高度( width : 200, height : 200)

变化步长一样( 10 )

变化时间一样( 每30毫秒变化一次 )

目标( width: 500, height : 400 )

你能想到什么问题吗?( 两个人在同一起跑线上,速度一样, 时间一样,但是要同时到达不同的目标,一个500, 一个400 )

答案是很明显的,肯定是目标近的( height : 400 )那个先到达,然后把对象上的定时器关了,另一个目标更远的( width: 500 )肯定到达不了

你可以在这句代码下面,输出当前的值和目标值:

var target = attr[key];
console.log( key, cur, target );

输出来的结果是:

从上图可以看出,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的时候再关闭定时器,不就在同一时间,完成了同时到达目标的效果吗?

修改后的代码如下:

 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>

View Code

声明一个变量,每次变化完一次( width, height )样式 把bFlag = true, 只要在for循环中有一个没有到达目标,bFlag的值都是false,这样就不会关闭定时器。当两个都到达目标,才关闭定时器.

三、顺序运动

如样式变化,按顺序来,不是同时变化, 如:

oBox.onmouseover = function(){
//回调函数: 把函数当做参数传递给另一个函数
  animate( this, { 'width' : 500 }, 10, function(){
    animate( this, { 'height' : 500 }, 10 );
  } );
}

当把width变成500px的时候,如果传递了回调函数, 再接着执行回调函数里面的运动

修改后的完整代码:

 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>

View Code

[js高手之路]打造通用的匀速运动框架相关推荐

  1. HTML一条线匀速一定区域运动,通用的匀速运动框架如何打造

    本文主要为大家带来一篇打造通用的匀速运动框架(实例讲解).小编觉得挺不错的,现在就分享给大家,也给大家做个参考.一起跟随小编过来看看吧,希望能帮助到大家. 本文,是接着上 基于匀速运动的实例讲解(侧边 ...

  2. 原生js由html创建节点,[js高手之路]HTML标签解释成DOM节点的实现方法

    最近在封装一个开源框架,已经写了500行, 已经具备jquery的大多数常用功能,后面还会扩展大量的工具函数和MVVM双向驱动等功能.跟jquery的使用方法完全一样,jquery的选择器,几乎都能支 ...

  3. [js高手之路]设计模式系列课程-发布者,订阅者重构购物车

    发布者订阅者模式,是一种很常见的模式,比如: 一.买卖房子 生活中的买房,卖房,中介就构成了一个发布订阅者模式,买房的人,一般需要的是房源,价格,使用面积等信息,他充当了订阅者的角色 中介拿到卖主的房 ...

  4. [js高手之路]深入浅出webpack教程系列9-打包图片(file-loader)用法

    [js高手之路]深入浅出webpack教程系列索引目录: [js高手之路]深入浅出webpack教程系列1-安装与基本打包用法和命令参数 [js高手之路]深入浅出webpack教程系列2-配置文件we ...

  5. [js高手之路]从原型链开始图解继承到组合继承的产生

    于javascript原型链的层层递进查找规则,以及原型对象(prototype)的共享特性,实现继承是非常简单的事情 一.把父类的实例对象赋给子类的原型对象(prototype),可以实现继承 1 ...

  6. [js高手之路]原型对象(prototype)与原型链相关属性与方法详解

    一,instanceof: instanceof检测左侧的__proto__原型链上,是否存在右侧的prototype原型. 我在之前的两篇文章 [js高手之路]构造函数的基本特性与优缺点 [js高手 ...

  7. [js高手之路] html5 canvas系列教程 - 线条样式(lineWidth,lineCap,lineJoin,setLineDash)

    上文,写完弧度与贝塞尔曲线[js高手之路] html5 canvas系列教程 - arcTo(弧度与二次,三次贝塞尔曲线以及在线工具),本文主要是关于线条的样式设置 lineWidth: 设置线条的宽 ...

  8. [js高手之路] html5 canvas系列教程 - 掌握画直线图形的常用API

    我们接着上文[js高手之路] html5 canvas系列教程 - 认识canvas以及基本使用方法继续. 一.直线的绘制 cxt.moveTo( x1, y1 ): 将画笔移动到x1, y1这个点 ...

  9. [js高手之路] es6系列教程 - 迭代器与生成器详解

    什么是迭代器? 迭代器是一种特殊对象,这种对象具有以下特点: 1,所有对象都有一个next方法 2,每次调用next方法,都会返回一个对象,该对象包含两个属性,一个是value, 表示下一个将要返回的 ...

最新文章

  1. 工业环境中对机器学习的行业视角
  2. 《架构漫谈》读书笔记五
  3. C++运算符重载-mfc演示
  4. 联想微型计算机电脑黑屏怎么做系统,联想电脑黑屏怎么办,5种方法轻松排除黑屏故障...
  5. 授权函php还是提示没权限_大快人心,只需一招,BAT 毒瘤再也不敢滥用权限
  6. jquery SELECT 操作
  7. Android Studio Cmake C++ JNI demo
  8. 公共技术点之 Android 动画基础
  9. CentOS 7 配置DHCP服务器
  10. CSDN会员免费拿,实现CSDN会员自由的机会到了!!!
  11. C# OCR 文字识别
  12. 光缆故障定位检测仪使用方法简介
  13. 计算机如何打开无线网络适配器,如何解决网络适配器无法启动无线网卡的问题...
  14. 在java中使用RBL服务器(中国反垃圾邮件联盟的CBL+使用)
  15. 红孩儿编辑器的模块设计6
  16. sip协议之网络传输方式
  17. 微网通联 一键认证iOS开发文档
  18. PHP系列之集成Ajax实现登录验证
  19. 计算机一会儿黑屏,电脑一会黑屏一会亮怎么处理?
  20. FPGA实现深度学习系列之卷积神经网络算法描述

热门文章

  1. 常考数据结构与算法:异或操作
  2. 线程:方法join的使用
  3. python二十九:文件夹,包
  4. requireJS文件夹
  5. jquery遍历集合数组标签
  6. 如何在一个程序集中序列化在另一个中反序列化
  7. 测试JdbcTemplate执行SQL语句和存储过程
  8. 求android实现未读短信图标数字提示效果
  9. Unsafe(转载)
  10. python furl模块 网址修改 参数解析