forked from newxps/move
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmove.js
192 lines (158 loc) · 4.23 KB
/
move.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/* move.js
* @author:flfwzgl https://github.com/flfwzgl
* @copyright: MIT license */
!function(){
var Move = function(){};
var curve = Move.prototype = {
extend: function(obj){
for(var k in obj){
if(k in curve){
try{
console.warn( k + '已经被修改!');
} catch(e){}
}
curve[k] = (function(moveType){
return function(){
return _doMove.call(this, arguments, moveType);
}
})(obj[k]);
}
}
}
// move中函数传入如下参数
// r => 过渡范围, 例如[0, 1000] (必须传, 且传数组)
// d => 过渡时间, ms, (可不传, 默认500)
// fn => 每一帧的回调函数, 传入当前过渡值v (必须传)
// fnEnd => 动画结束时回调 (可不传)
// 例如: m.ease([0, 1000], 500, function(v){ ... }, fnEnd)
// 注意: 这些参数的顺序可以打乱!!!
if(typeof module === 'object' && module.exports) {
module.exports = new Move;
} else {
if(window.move) {
try {
console.log('move has been declared!');
} catch(e) {}
} else {
window.move = new Move;
}
}
var request = window.requestAnimationFrame,
stopRequest = window.cancelAnimationFrame
var _move, _stopMove;
//初始化运动函数和停止函数
if(request) {
_move = function(fn, timer){
var step = function() {
if(!fn()) timer.id = request(step);
}
step();
}
} else {
_move = function(fn, timer) {
timer.id = setInterval(fn, 16);
}
}
if(stopRequest) {
_stopMove = function(timer) {
stopRequest(timer.id);
}
} else {
_stopMove = function(timer) {
clearInterval(timer.id);
}
}
//开始动画函数
function _doMove(arg, moveType){
var r, d, fn, fnEnd;
// 严格限制传入参数, 且传入的参数可以没有顺序
for(var i = 0; i < 4; i++){
if(typeof arg[i] === 'object' && !r) r = arg[i];
else if(typeof arg[i] === 'number' && !d) d = arg[i];
else if(typeof arg[i] === 'function' && !fn) fn = arg[i];
else if(typeof arg[i] === 'function' && !fnEnd) fnEnd = arg[i];
}
if(!r instanceof Array || !fn) return;
d = d || 500;
var from = +new Date, //起始时间
x = 0,
y,
a = r[0],
b = r[1];
var timer = 't' + Math.random();
var self = this;
//用于保存定时器ID的对象, requestAnimation递归调用必须传入对象
this[timer] = {};
_move(function(){
x = (+new Date - from)/d;
if(x >= 1){
// 动画结束
fn(b);
if(fnEnd) fnEnd();
return true;
} else {
y = moveType(x);
fn(a + (b - a) * y);
}
}, self[timer]);
return function(){
_stopMove(self[timer]);
return a + (b - a) * y;
}
}
var PI = Math.PI,
sin = Math.sin,
cos = Math.cos,
pow = Math.pow,
abs = Math.abs,
sqrt = Math.sqrt;
/***** 动画曲线 ******/
curve.extend({
//定义域和值域均为[0, 1], 传入自变量x返回对应值y
//先加速后减速
ease: function(x){
// return -0.5*cos(PI * (2 - x)) + 0.5;
if(x <= 0.5) return 2*x*x;
else if(x > 0.5) return -2*x*x + 4*x - 1;
},
// 初速度为0 ,一直加速
easeIn: function(x){
return x*x;
},
//先慢慢加速1/3, 然后突然大提速, 最后减速
ease2: function(x){
return x < 1/3 ? x*x : -2*x*x + 4*x - 1;
},
//初速度较大, 一直减速, 缓冲动画
easeOut: function(x){
return pow(x, 0.8);
},
//碰撞动画
collision: function(x){
var a, b; //a, b代表碰撞点的横坐标
for(var i = 1, m = 20; i < m; i++){
a = 1 - (4/3) * pow(0.5, i - 1);
b = 1 - (4/3) * pow(0.5, i);
if(x >= a && x <= b ){
return pow(3*(x - (a + b)/2 ), 2) + 1 - pow(0.25, i - 1);
}
}
},
//弹性动画
elastic: function(x){
return -pow(1/12, x) * cos( PI*2.5*x*x ) + 1;
},
//匀速动画
linear: function(x){
return x;
},
//断断续续加速减速
wave: function(x){
return (1/12)*sin( 5*PI*x ) + x;
},
//先向反方向移动一小段距离, 然后正方向移动, 并超过终点一小段, 然后回到终点
opposite: function(x){
return (sqrt(2)/2)*sin( (3*PI/2)*(x - 0.5) ) + 0.5;
}
})
}();