---来自一个前端妹子
1 <!DOCTYPE html>
2 <html>
3 <head lang="en">
4 <meta charset="UTF-8">
5 <title></title>
6
7
8 <!--
9 先快后慢
10 一开始的步子要迈的大,后面的步子要小
11
12 步子要越来越小
13
14 被除数 / 10 ,被除数的值越大,结果就越大,被除数越小。值就越小
15
16 所以我们要找到一个越来越小的数,再去除以10,把结果作为步长,就能起到步子越来越小
17
18 到底什么是越来越小的值?到目标的距离,是越来越小的
19
20
21 当前距离 目标 基数(除数)
22 0 400 10 400 - 0 = 400 / 10 = 40 这步走40
23 40 400 10 400 - 40 = 360 / 10 = 36 这步走36
24
25 76 400 10 400 - 76 = 324 / 10 = 32.4 向上取整变成了33 这步走33
26 109 400 10 400 - 109 = 291 / 10 = 29.1 取整变 30
27 ………………………………………………………………………………
28 390 400 10 400 - 390 = 10 / 10 = 1 这步走1
29 391 400 10 400 - 391 = 9 / 10 = 0.9 向上取整走1
30 越到后面越慢,而且到最后那几步就是1个像素1个像素的走,能走到,而且绝对不会超
31
32 399 400 10 400 - 399 = 1 / 10 = 0.1 向上取整变1
33
34 -->
35
36
37 <style>
38
39 #box {
40 width: 100px;
41 height: 100px;
42 background-color: red;
43 position: absolute;
44 }
45
46 </style>
47 </head>
48 <body>
49
50 <input type="button" value="移动到400" id="move400"/>
51 <input type="button" value="移动到800" id="move800"/>
52
53 <div id="box"></div>
54
55 </body>
56 </html>
57
58 <script>
59
60 //找到div
61 var box = document.getElementById("box");
62
63 //移动到400的点击事件
64 document.getElementById("move400").onclick = function () {
65
66 animateSlow(400);
67 }
68
69
70 document.getElementById("move800").onclick = function () {
71
72 animateSlow(800);
73 }
74
75
76 var timerID;
77 function animateSlow(target) {
78
79 clearInterval(timerID);
80
81 timerID = setInterval(function () {
82
83 //获取到当前的位置
84 var current = box.offsetLeft;
85
86 //用目标 - 当前位置 得到距离 ,再用距离除以10,再向上取整得到步长
87 var step = Math.ceil((target - current) / 10);
88
89 //因为绝对不会超,所以算出步长后直接走这一步就行了
90 current += step;
91
92 //设置给要移动的元素
93 box.style.left = current + "px";
94
95 console.log("当前位置:" + current + "------步长:" + step);
96
97 //如果到了目的地,就停止计时器
98 if (current == target) {
99
100 clearInterval(timerID);
101 }
102
103 }, 50
104 )
105 }
106
107
108 </script>
01-缓动动画的封装之可以移动到不同的目标距离.html
先快后慢
一开始的步子要迈的大,后面的步子要小
步子要越来越小
被除数 / 10 ,被除数的值越大,结果就越大,被除数越小。值就越小
所以我们要找到一个越来越小的数,再去除以10,把结果作为步长,就能起到步子越来越小
到底什么是越来越小的值?到目标的距离,是越来越小的
当前距离 目标 基数(除数)
0 400 10 400 - 0 = 400 / 10 = 40 这步走40
40 400 10 400 - 40 = 360 / 10 = 36 这步走36
76 400 10 400 - 76 = 324 / 10 = 32.4 向上取整变成了33 这步走33
109 400 10 400 - 109 = 291 / 10 = 29.1 取整变 30
………………………………………………………………………………
390 400 10 400 - 390 = 10 / 10 = 1 这步走1
391 400 10 400 - 391 = 9 / 10 = 0.9 向上取整走1
越到后面越慢,而且到最后那几步就是1个像素1个像素的走,能走到,而且绝对不会超
399 400 10 400 - 399 = 1 / 10 = 0.1 向上取整变1
1 <!DOCTYPE html>
2 <html>
3 <head lang="en">
4 <meta charset="UTF-8">
5 <title></title>
6
7
8 <style>
9 div {
10 width: 100px;
11 height: 100px;
12 background-color: red;
13 position: absolute;
14 }
15
16 #blue {
17 background-color: blue;
18 top: 150px;
19 }
20
21 </style>
22
23 </head>
24 <body>
25
26 <input type="button" value="移动到红" id="moveRed"/>
27 <input type="button" value="移动到蓝" id="moveBlue"/>
28
29 <div id="red"></div>
30 <div id="blue"></div>
31
32 </body>
33 </html>
34
35 <script>
36 var red = document.getElementById("red");
37 var blue = document.getElementById("blue");
38
39 document.getElementById("moveRed").onclick = function () {
40 animateSlow(red, 400);
41 };
42
43 document.getElementById("moveBlue").onclick = function () {
44
45 animateSlow(blue, 400);
46 };
47
48
49
50 /*
51
52 第二重封装:
53 解决了可以移动不同元素的问题
54 以及移动第二个会停止第一个元素的问题(自己的只能自己停)
55
56 */
57
58 function animateSlow(obj, target) {
59
60 clearInterval(obj.timerID);
61
62 obj.timerID = setInterval(function () {
63
64 //获取到当前的位置
65 var current = obj.offsetLeft;
66
67 //用目标 - 当前位置 得到距离 ,再用距离除以10,再向上取整得到步长
68 var step = Math.ceil((target - current) / 10);
69
70 //因为绝对不会超,所以算出步长后直接走这一步就行了
71 current += step;
72
73 //设置给要移动的元素
74 obj.style.left = current + "px";
75
76 console.log("当前位置:" + current + "------步长:" + step);
77
78 //如果到了目的地,就停止计时器
79 if (current == target) {
80
81 clearInterval(obj.timerID);
82 }
83
84 }, 50
85 )
86 }
87 </script>
02-缓动动画的封装之各种对象可以动.html
第二重封装:
解决了可以移动不同元素的问题
以及移动第二个会停止第一个元素的问题(自己的只能自己停)
1 <!DOCTYPE html>
2 <html>
3 <head lang="en">
4 <meta charset="UTF-8">
5 <title></title>
6
7 <!--
8 当前位置 目标位置 基数
9 800 400 10 400 -800 = -400 /10 = -40
10 760 400 10 400 - 760 = -360 / 10 = -36
11 .....................
12
13 409 400 10 400 - 409 = -9 / 10 = -0.9 向下取整变-1
14 408 400
15 407
16 406
17 400
18
19 如果是往右走
20
21 791 800 10 800-791 = 9 /10 = 0.9 要向上取整才正确
22
23 我们发现有的时候要向上,有的时候要向下
24
25 如果最终算出的结果为负数,一定要向下,如果算出的结果为正数,要向上
26 -->
27
28
29 <style>
30 div {
31 width: 100px;
32 height: 100px;
33 background-color: red;
34 position: absolute;
35 }
36
37
38 </style>
39
40 </head>
41 <body>
42
43 <input type="button" value="移动到400" id="move400"/>
44 <input type="button" value="移动到800" id="move800"/>
45
46 <div id="red"></div>
47
48 </body>
49 </html>
50
51 <script>
52 var red = document.getElementById("red");
53 var blue = document.getElementById("blue");
54
55 document.getElementById("move400").onclick = function () {
56
57 animateSlow(red, 400);
58 };
59
60 document.getElementById("move800").onclick = function () {
61
62 animateSlow(red, 800);
63 };
64
65
66 /*
67
68 第三重封装:
69 解决了既可以往右走,也可以往走的问题
70
71 发现:只要看算出的结果,如果是正就要向上取整,如果是负就要向下取整
72
73
74
75 */
76
77 function animateSlow(obj, target) {
78
79 clearInterval(obj.timerID);
80
81 obj.timerID = setInterval(function () {
82
83 //获取到当前的位置
84 var current = obj.offsetLeft;
85
86 //先用目标-当前位置,再除以基数得到结果
87 var result = (target - current) / 10;
88
89 //如果结果是正就用向上取整,如果是负就用 向下取整
90 var step = result > 0 ? Math.ceil(result) : Math.floor(result);
91
92 //因为绝对不会超,所以算出步长后直接走这一步就行了
93 current += step;
94
95 //设置给要移动的元素
96 obj.style.left = current + "px";
97
98 console.log("当前位置:" + current + "------步长:" + step);
99
100 //如果到了目的地,就停止计时器
101 if (current == target) {
102
103 clearInterval(obj.timerID);
104 }
105
106 }, 50
107 )
108 }
109 </script>
03-缓动动画的封装完成往左往右动.html
当前位置 目标位置 基数
800 400 10 400 -800 = -400 /10 = -40
760 400 10 400 - 760 = -360 / 10 = -36
.....................
409 400 10 400 - 409 = -9 / 10 = -0.9 向下取整变-1
408 400
407
406
400
如果是往右走
791 800 10 800-791 = 9 /10 = 0.9 要向上取整才正确
我们发现有的时候要向上,有的时候要向下
如果最终算出的结果为负数,一定要向下,如果算出的结果为正数,要向上
第三重封装:
解决了既可以往右走,也可以往走的问题
发现:只要看算出的结果,如果是正就要向上取整,如果是负就要向下取整
1 <!DOCTYPE html>
2 <html>
3 <head lang="en">
4 <meta charset="UTF-8">
5 <title></title>
6
7 <style>
8 #box {
9 width: 100px;
10 height: 100px;
11 background-color: red;
12 position: absolute;
13 }
14
15 /*
16 第四重封装:
17 解决了可以改动上下移动和左右移动以及宽高变化的问题
18
19 加一个参数:参数传入一个你需要改动的属性
20
21 然后再通过我们封装的获取样式的方法,获取到当前的值
22 算法不变
23
24 只不过赋值时,就根据你传入的参数来赋值到对应的属性
25
26 */
27 </style>
28 </head>
29 <body>
30
31 <input type="button" value="向下走500" id="down500"/>
32 <input type="button" value="向右走500" id="right500"/>
33 <input type="button" value="变宽到400" id="width400"/>
34 <input type="button" value="变高到400" id="height400"/>
35
36 <div id="box"></div>
37
38 </body>
39 </html>
40
41
42 <script src="common.js"></script>
43 <script>
44 //找到div
45 var box = document.getElementById("box");
46
47 document.getElementById("down500").onclick = function () {
48
49 animateSlow(box, 500, "top");
50 };
51
52
53 document.getElementById("right500").onclick = function () {
54
55 animateSlow(box, 500, "left");
56 };
57
58 document.getElementById("width400").onclick = function () {
59
60 animateSlow(box, 400, "width");
61 };
62
63 document.getElementById("height400").onclick = function () {
64
65 animateSlow(box, 400, "height");
66 };
67
68
69 function animateSlow(obj, target, attr) {//可能传left,也可能传top
70
71 clearInterval(obj.timerID);
72
73 obj.timerID = setInterval(function () {
74
75 //获取到当前的位置
76 //传入的是什么属性就获取什么属性的样式,因为得到的是带单位的字符串,所以要用parseInt做一个转换
77 var current = parseInt(getStyle(obj, attr));
78
79 //先用目标-当前位置,再除以基数得到结果
80 var result = (target - current) / 10;
81
82 //如果结果是正就用向上取整,如果是负就用 向下取整
83 var step = result > 0 ? Math.ceil(result) : Math.floor(result);
84
85 //因为绝对不会超,所以算出步长后直接走这一步就行了
86 current += step;
87
88 //设置给要移动的元素
89 obj.style[attr] = current + "px";
90
91 console.log("当前位置:" + current + "------步长:" + step);
92
93 //如果到了目的地,就停止计时器
94 if (current == target) {
95
96 clearInterval(obj.timerID);
97 }
98
99 }, 50
100 )
101 }
102 </script>
04-缓动动画的封装之实现上下宽高可以用动画变化.html
第四重封装:
解决了可以改动上下移动和左右移动以及宽高变化的问题
加一个参数:参数传入一个你需要改动的属性
然后再通过我们封装的获取样式的方法,获取到当前的值
算法不变
只不过赋值时,就根据你传入的参数来赋值到对应的属性
1 <!DOCTYPE html>
2 <html>
3 <head lang="en">
4 <meta charset="UTF-8">
5 <title></title>
6
7 <style>
8 #box {
9 width: 100px;
10 height: 100px;
11 background-color: red;
12 position: absolute;
13 }
14
15 /*
16 第五重封装:
17 解决了可以同时改多个属性的问题
18
19 1.把函数的参数精简为2个,1个为接受要改的元素,第二个就是接收对象
20 对象里面放你要改的属性(对象的属性)和它对应的目标(属性的值)
21
22 2.在计时器里遍历接收对象的那个参数,取到key,key就是我们要取到的样式的属性,以及要改的属性
23 算法不变,只是取属性时用key来取了
24
25 3.不能哪一个到了目标就停止计时器,而应该是全部到了才停止计时器
26 用一个标记来标记,只要有一个没到,就改成false,循环外面判断是否还是为true,还是为true就代表都到了,都到了就停止计时器
27
28 */
29 </style>
30 </head>
31 <body>
32
33 <input type="button" value="同时向右走到500向下走到400" id="btn"/>
34
35
36 <div id="box"></div>
37
38 </body>
39 </html>
40
41
42 <script src="common.js"></script>
43 <script>
44
45
46 //找到div
47 var box = document.getElementById("box");
48
49 document.getElementById("btn").onclick = function () {
50
51 /*
52 我们现在需要同时改多个属性,而且多个属性可能有不同的不表
53 那么如果用以前的那种加参数方式不行,因为假如说要改3个属性,就需要6个,到时再临时加参数肯定不行
54 我想用一个参数,既可以让你传入一个属性和一个目标
55 也可以传入多个属性加多个目标
56 */
57
58 var att = {
59
60 left: 500,
61 top: 400,
62 400,
63 height: 400,
64 }
65
66 animateSlow(box, att);
67 };
68
69
70 function animateSlow(obj, attrs) {//可能传left,也可能传top
71
72 clearInterval(obj.timerID);
73
74 obj.timerID = setInterval(function () {
75
76 //我先默认认为所有的都到了目的地(标记为true),在循环里,我判断一下,只要有一个不到,我就把标记改为false
77
78 //默认先认为都到了
79 var flag = true;
80
81 //把所有的属性名取出来
82 for (var key in attrs) { // left: 500 top: 400
83
84 //获取到当前的位置
85 //传入的是什么属性就获取什么属性的样式,因为得到的是带单位的字符串,所以要用parseInt做一个转换
86 var current = parseInt(getStyle(obj, key));
87
88 //先用目标-当前位置,再除以基数得到结果
89 //注意:此时目标是它的key所对应的值
90 var result = (attrs[key] - current) / 10;
91
92 //如果结果是正就用向上取整,如果是负就用 向下取整
93 var step = result > 0 ? Math.ceil(result) : Math.floor(result);
94
95 //因为绝对不会超,所以算出步长后直接走这一步就行了
96 current += step;
97
98 //设置给要移动的元素
99 obj.style[key] = current + "px";
100
101 console.log("当前位置:" + current + "------步长:" + step);
102
103 //只要有一个没到,就不要停计时器
104 if (current != attrs[key]) {
105
106 flag = false;
107 }
108 }
109
110 //如果这个值还是为true,就代表所有的属性都到了目的地
111 if (flag) {
112
113 clearInterval(obj.timerID);
114 }
115
116 }, 50)
117 }
118 </script>
05-缓动动画的封装之实现斜着走.html
第五重封装:
我们现在需要同时改多个属性,而且多个属性可能有不同的不表
那么如果用以前的那种加参数方式不行,因为假如说要改3个属性,就需要6个,到时再临时加参数肯定不行
我想用一个参数,既可以让你传入一个属性和一个目标
也可以传入多个属性加多个目标
1 <!DOCTYPE html>
2 <html>
3 <head lang="en">
4 <meta charset="UTF-8">
5 <title></title>
6
7
8 <!--
9 这一重解决了:
10 1.透明度不可以改的问题(解决为可以改)
11 1.1 因为透明度特殊,所以单独在forin里用一个if判断,如果key等于opacity,那么就走opacity的代码,else就走以前写的代码
12 1.2 在opacity里,代码跟以前的代码几乎一样,只改动以下几个部分
13 1.2.1 把parseInt改成parseFloat ,再取到值以后给当前位置和目标位置先乘以100
14 1.2.2 在赋值到元素的opacity之前,先除以100
15 1.2.3 在赋值时去掉px
16
17
18 2.增加动画完成后可以执行你想做的事的代码(回调函数)
19 2.1 先增加一个参数,用来接收用户传入的函数
20 2.2 在清除计时器的代码后面,先判断是不是函数,如果是,就调用
21
22 -->
23
24 <style>
25 #box {
26 width: 100px;
27 height: 100px;
28 background-color: red;
29 position: absolute;
30 }
31
32 </style>
33 </head>
34 <body>
35
36 <input type="button" value="同时向右走到500向下走到400" id="btn"/>
37
38
39 <div id="box"></div>
40
41 </body>
42 </html>
43
44
45 <script src="common.js"></script>
46 <script>
47
48
49 //找到div
50 var box = document.getElementById("box");
51
52 document.getElementById("btn").onclick = function () {
53
54 /*
55 我们现在需要同时改多个属性,而且多个属性可能有不同的不表
56 那么如果用以前的那种加参数方式不行,因为假如说要改3个属性,就需要6个,到时再临时加参数肯定不行
57 我想用一个参数,既可以让你传入一个属性和一个目标
58 也可以传入多个属性加多个目标
59 */
60
61 var att = {
62
63 opacity: 0,
64 left: 500,
65 top: 400,
66 300,
67 height: 300
68 }
69
70 animateSlow(box, att, function () {
71
72 var attrs = {
73
74 top: 31,
75 left: 1000,
76 100,
77 height: 100,
78 opacity: 1
79 }
80 animateSlow(box, attrs);
81 });
82 };
83
84
85 function animateSlow(obj, attrs, fn) {//可能传left,也可能传top
86
87 clearInterval(obj.timerID);
88
89 obj.timerID = setInterval(function () {
90
91 //我先默认认为所有的都到了目的地(标记为true),在循环里,我判断一下,只要有一个不到,我就把标记改为false
92
93 //默认先认为都到了
94 var flag = true;
95
96 //把所有的属性名取出来
97 for (var key in attrs) { // left: 500 top: 400
98
99 if (key == "opacity") {
100
101 //获取到当前的位置
102 //传入的是什么属性就获取什么属性的样式,因为得到的是带单位的字符串,所以要用parseInt做一个转换
103 var current = parseFloat(getStyle(obj, key)) * 100;
104
105 //它的值太小了
106 //先用目标-当前位置,再除以基数得到结果
107 //注意:此时目标是它的key所对应的值
108 var result = (attrs[key] * 100 - current) / 10;
109
110 //如果结果是正就用向上取整,如果是负就用 向下取整
111 var step = result > 0 ? Math.ceil(result) : Math.floor(result);
112
113 //因为绝对不会超,所以算出步长后直接走这一步就行了
114 current += step;
115
116 //之前你是先乘以100做的运算,所以后面应该把再除以100
117 current /= 100;
118 //设置给要移动的元素
119 obj.style[key] = current;
120
121 console.log("当前位置:" + current + "------步长:" + step);
122
123 //只要有一个没到,就不要停计时器
124 if (current != attrs[key]) {
125
126 flag = false;
127 }
128
129 } else {
130
131 //获取到当前的位置
132 //传入的是什么属性就获取什么属性的样式,因为得到的是带单位的字符串,所以要用parseInt做一个转换
133 var current = parseInt(getStyle(obj, key));
134
135 //先用目标-当前位置,再除以基数得到结果
136 //注意:此时目标是它的key所对应的值
137 var result = (attrs[key] - current) / 10;
138
139 //如果结果是正就用向上取整,如果是负就用 向下取整
140 var step = result > 0 ? Math.ceil(result) : Math.floor(result);
141
142 //因为绝对不会超,所以算出步长后直接走这一步就行了
143 current += step;
144
145 //设置给要移动的元素
146 obj.style[key] = current + "px";
147
148 console.log("当前位置:" + current + "------步长:" + step);
149
150 //只要有一个没到,就不要停计时器
151 if (current != attrs[key]) {
152
153 flag = false;
154 }
155 }
156 }
157
158 //如果这个值还是为true,就代表所有的属性都到了目的地
159 if (flag) {
160
161 clearInterval(obj.timerID);
162
163 //这里的代码不要写死,就让别人把要结束时执行的代码传进来
164 //你传的是什么代码,我执行的就是什么代码
165 if (fn instanceof Function) {
166 fn();
167 }
168
169 }
170
171 }, 50)
172 }
173 </script>
06-缓动动画的封装终极封装.html
这一重解决了:
1.透明度不可以改的问题(解决为可以改)
1.1 因为透明度特殊,所以单独在forin里用一个if判断,如果key等于opacity,那么就走opacity的代码,else就走以前写的代码
1.2 在opacity里,代码跟以前的代码几乎一样,只改动以下几个部分
1.2.1 把parseInt改成parseFloat ,再取到值以后给当前位置和目标位置先乘以100
1.2.2 在赋值到元素的opacity之前,先除以100
1.2.3 在赋值时去掉px
2.增加动画完成后可以执行你想做的事的代码(回调函数)
2.1 先增加一个参数,用来接收用户传入的函数
2.2 在清除计时器的代码后面,先判断是不是函数,如果是,就调用