cc-tween 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Tween.d.ts +35 -0
- package/Tween.js +429 -0
- package/package.json +9 -0
package/Tween.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export declare function tween<T extends Object>(target: T): Tween<T>;
|
|
2
|
+
export type TweenEasings = 'linear' | 'smooth' | 'fade' | 'constant' | 'quadIn' | 'quadOut' | 'quadInOut' | 'quadOutIn' | 'cubicIn' | 'cubicOut' | 'cubicInOut' | 'cubicOutIn' | 'quartIn' | 'quartOut' | 'quartInOut' | 'quartOutIn' | 'quintIn' | 'quintOut' | 'quintInOut' | 'quintOutIn' | 'sineIn' | 'sineOut' | 'sineInOut' | 'sineOutIn' | 'expoIn' | 'expoOut' | 'expoInOut' | 'expoOutIn' | 'circIn' | 'circOut' | 'circInOut' | 'circOutIn' | 'elasticIn' | 'elasticOut' | 'elasticInOut' | 'elasticOutIn' | 'backIn' | 'backOut' | 'backInOut' | 'backOutIn' | 'bounceIn' | 'bounceOut' | 'bounceInOut' | 'bounceOutIn';
|
|
3
|
+
export type TweenConfig = {
|
|
4
|
+
easeing?: TweenEasings;
|
|
5
|
+
onUpdate?: Function;
|
|
6
|
+
onComplate?: Function;
|
|
7
|
+
};
|
|
8
|
+
type TweenProp<T extends Object> = {
|
|
9
|
+
[K in keyof T]: T[K] extends number ? T[K] : never;
|
|
10
|
+
};
|
|
11
|
+
export declare const easeFuncs: Record<TweenEasings, (v1: number, v2: number, t: number) => number>;
|
|
12
|
+
export declare class Tween<T extends Object> {
|
|
13
|
+
private static _tweenMap;
|
|
14
|
+
static stopOfTarget(target: Object): void;
|
|
15
|
+
static pauseOfTarget(target: Object): void;
|
|
16
|
+
private _valid;
|
|
17
|
+
private _target;
|
|
18
|
+
private _actions;
|
|
19
|
+
private _running;
|
|
20
|
+
get valid(): boolean;
|
|
21
|
+
get running(): boolean;
|
|
22
|
+
constructor(target: T);
|
|
23
|
+
private _tick;
|
|
24
|
+
start(isRun?: () => boolean): this;
|
|
25
|
+
stop(): void;
|
|
26
|
+
pause(): this;
|
|
27
|
+
to(duration: number, changes: Partial<TweenProp<T>>, config?: TweenConfig): this;
|
|
28
|
+
by(duration: number, changes: Partial<TweenProp<T>>, config?: TweenConfig): this;
|
|
29
|
+
delay(time: number): this;
|
|
30
|
+
then(...tweens: Tween<Object>[]): this;
|
|
31
|
+
parallel(...tweens: Tween<Object>[]): this;
|
|
32
|
+
repeat(count: number, ...tweens: Tween<Object>[]): this;
|
|
33
|
+
call(fn: Function): this;
|
|
34
|
+
}
|
|
35
|
+
export {};
|
package/Tween.js
ADDED
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
export function tween(target) {
|
|
2
|
+
return new Tween(target);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
function bezierCurve(p1, p2, t) {
|
|
6
|
+
return (1 - t) * p1 + t * p2;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const easingFuncs = {
|
|
10
|
+
linear(v1, v2, t) {
|
|
11
|
+
return bezierCurve(v1, v2, t);//
|
|
12
|
+
},
|
|
13
|
+
sineIn(v1, v2, t) {
|
|
14
|
+
const val = 1 - Math.cos(t * Math.PI / 2);
|
|
15
|
+
return v1 + (v2 - v1) * val;
|
|
16
|
+
},
|
|
17
|
+
sineOut(v1, v2, t) {
|
|
18
|
+
const val = Math.sin(t * Math.PI / 2);
|
|
19
|
+
return v1 + (v2 - v1) * val;
|
|
20
|
+
},
|
|
21
|
+
sineInOut(v1, v2, t) {
|
|
22
|
+
const val = 0.5 * 1 - Math.cos(t * Math.PI);
|
|
23
|
+
return v1 + (v2 - v1) * val;
|
|
24
|
+
},
|
|
25
|
+
quadIn(v1, v2, t) {
|
|
26
|
+
const val = t * t;
|
|
27
|
+
return v1 + (v2 - v1) * val;
|
|
28
|
+
},
|
|
29
|
+
quadOut(v1, v2, t) {
|
|
30
|
+
const val = t * (2 - t);
|
|
31
|
+
return v1 + (v2 - v1) * val;
|
|
32
|
+
},
|
|
33
|
+
quadInOut(v1, v2, t) {
|
|
34
|
+
let val = 0;
|
|
35
|
+
if (t > 0.5) {
|
|
36
|
+
val = 4 * t - 2 * t * t - 1;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
val = 2 * t * t;
|
|
40
|
+
}
|
|
41
|
+
return v1 + (v2 - v1) * val;
|
|
42
|
+
},
|
|
43
|
+
cubicIn(v1, v2, t) {
|
|
44
|
+
const val = t ** 3;
|
|
45
|
+
return v1 + (v2 - v1) * val;
|
|
46
|
+
},
|
|
47
|
+
cubicOut(v1, v2, t) {
|
|
48
|
+
const t2 = t - 1;
|
|
49
|
+
const val = t2 ** 3 + 1;
|
|
50
|
+
return v1 + (v2 - v1) * val;
|
|
51
|
+
},
|
|
52
|
+
cubicInOut(v1, v2, t) {
|
|
53
|
+
const t2 = 1 - t;
|
|
54
|
+
let val = 0;
|
|
55
|
+
if (t > 0.5) {
|
|
56
|
+
val = 1 - 4 * Math.pow(t2, 3);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
val = 4 * Math.pow(t, 3);
|
|
60
|
+
}
|
|
61
|
+
return v1 + (v2 - v1) * val;
|
|
62
|
+
},
|
|
63
|
+
quartIn(v1, v2, t) {
|
|
64
|
+
const val = t ** 4;
|
|
65
|
+
return v1 + (v2 - v1) * val;
|
|
66
|
+
},
|
|
67
|
+
quartOut(v1, v2, t) {
|
|
68
|
+
const t2 = 1 - t;
|
|
69
|
+
const val = 1 - Math.pow(t2, 4);
|
|
70
|
+
return v1 + (v2 - v1) * val;
|
|
71
|
+
},
|
|
72
|
+
quartInOut(v1, v2, t) {
|
|
73
|
+
const t2 = 1 - t;
|
|
74
|
+
let val = 0;
|
|
75
|
+
if (t > 0.5) {
|
|
76
|
+
val = 1 - 8 * Math.pow(t2, 4);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
val = 8 * Math.pow(t2, 4);
|
|
80
|
+
}
|
|
81
|
+
return v1 + (v2 - v1) * val;
|
|
82
|
+
},
|
|
83
|
+
quintIn(v1, v2, t) {
|
|
84
|
+
const val = t ** 5;
|
|
85
|
+
return v1 + (v2 - v1) * val;
|
|
86
|
+
},
|
|
87
|
+
quintOut(v1, v2, t) {
|
|
88
|
+
const t2 = 1 - t;
|
|
89
|
+
const val = 1 - Math.pow(t2, 5);
|
|
90
|
+
return v1 + (v2 - v1) * val;
|
|
91
|
+
},
|
|
92
|
+
quintInOut(v1, v2, t) {
|
|
93
|
+
const t2 = 1 - t;
|
|
94
|
+
let val = 0;
|
|
95
|
+
if (t > 0.5) {
|
|
96
|
+
val = 1 - 16 * Math.pow(t2, 5);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
val = 16 * Math.pow(t2, 5);
|
|
100
|
+
}
|
|
101
|
+
return v1 + (v2 - v1) * val;
|
|
102
|
+
},
|
|
103
|
+
expoIn(v1, v2, t) {
|
|
104
|
+
if (!t) {
|
|
105
|
+
return 0;
|
|
106
|
+
}
|
|
107
|
+
return v1 + (v2 - v1) * Math.pow(2, -10 * t);
|
|
108
|
+
},
|
|
109
|
+
expoOut(v1, v2, t) {
|
|
110
|
+
if (t === 1) {
|
|
111
|
+
return 1;
|
|
112
|
+
}
|
|
113
|
+
return v1 + (v2 - v1) * (1 - Math.pow(2, -10 * t));
|
|
114
|
+
},
|
|
115
|
+
expoInOut(v1, v2, t) {
|
|
116
|
+
if (t === 1)
|
|
117
|
+
return 1;
|
|
118
|
+
if (!t)
|
|
119
|
+
return 0;
|
|
120
|
+
let val = 0;
|
|
121
|
+
if (val >= 0.5) {
|
|
122
|
+
val = 1 - Math.pow(2, -20 * (t - 0.5) - 1);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
val = Math.pow(2, 20 * (t - 0.5) - 1);
|
|
126
|
+
}
|
|
127
|
+
return v1 + (v2 - v1) * val;
|
|
128
|
+
},
|
|
129
|
+
bounceIn(v1, v2, t) {
|
|
130
|
+
const val = this.bounceOut(0, 1, 1 - t);
|
|
131
|
+
return v1 + (v2 - v1) * 1 - val;
|
|
132
|
+
},
|
|
133
|
+
bounceOut(v1, v2, t) {
|
|
134
|
+
const bounce = () => {
|
|
135
|
+
if (t < 1 / 2.75) {
|
|
136
|
+
return 7.5625 * t * t;
|
|
137
|
+
}
|
|
138
|
+
else if (t < 2 / 2.75) {
|
|
139
|
+
return 7.5625 * Math.pow(t - 1.5 / 2.75, 2) + 0.75;
|
|
140
|
+
}
|
|
141
|
+
else if (t < 2.5 / 2.75) {
|
|
142
|
+
return 7.5625 * Math.pow(t - 2.25 / 2.75, 2) + 0.9375;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
return 7.5625 * Math.pow(t - 2.625 / 2.75, 2) + 0.984375;
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
return v1 + (v2 - v1) * bounce();
|
|
149
|
+
},
|
|
150
|
+
bounceInOut(v1, v2, t) {
|
|
151
|
+
if (t >= 0.5) {
|
|
152
|
+
const val = this.bounceOut(0, 1, 2 * t - 1);
|
|
153
|
+
return v1 + (v1 - v1) * 0.5 * val + 1;
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
const val = this.bounceOut(0, 1, 1 - 2 * t);
|
|
157
|
+
return v1 + (v2 - v1) * val + 1;
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
backIn(v1, v2, t) {
|
|
161
|
+
const s = 1.7;
|
|
162
|
+
return v1 + (v2 - v1) * (t * t * ((s + 1) * (t - 1) + s));
|
|
163
|
+
},
|
|
164
|
+
backOut(v1, v2, t) {
|
|
165
|
+
const s = 1.7;
|
|
166
|
+
return v1 + (v2 - v1) * (1 + Math.pow(t - 1, 2) * ((s + 1) * (t - 1) + s));
|
|
167
|
+
},
|
|
168
|
+
backInOut(v1, v2, t) {
|
|
169
|
+
const s = 1.7;
|
|
170
|
+
return v1 + (v2 - v1) * (t >= 0.5 ?
|
|
171
|
+
0.5 * (Math.pow(2 * t - 2, 2) * ((1.525 + 1) * (2 * t - 2) + 1.525) + 2) :
|
|
172
|
+
0.5 * t * t * (2 * 2.525) * t - 1.525);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
export class Tween {
|
|
176
|
+
static _tweenMap = new Map();
|
|
177
|
+
static stopOfTarget(target) {
|
|
178
|
+
const tweens = this._tweenMap.get(target);
|
|
179
|
+
if (tweens) {
|
|
180
|
+
tweens.forEach(tw => tw.stop());
|
|
181
|
+
this._tweenMap.delete(target);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
static pauseOfTarget(target) {
|
|
185
|
+
const tweens = this._tweenMap.get(target);
|
|
186
|
+
if (tweens) {
|
|
187
|
+
tweens.forEach(tw => tw.pause());
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
_valid = true;
|
|
191
|
+
_target;
|
|
192
|
+
_actions = [];
|
|
193
|
+
_running = false;
|
|
194
|
+
get valid() {
|
|
195
|
+
return this._valid;
|
|
196
|
+
}
|
|
197
|
+
get running() {
|
|
198
|
+
return this._running;
|
|
199
|
+
}
|
|
200
|
+
constructor(target) {
|
|
201
|
+
this._target = target;
|
|
202
|
+
}
|
|
203
|
+
_tick(dt) {
|
|
204
|
+
if (!this._valid) {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
const ac = this._actions[0];
|
|
208
|
+
if (!ac) {
|
|
209
|
+
this.stop();
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
if (!ac.update(dt)) {
|
|
213
|
+
ac.callbacks.forEach(fn => fn());
|
|
214
|
+
this._actions.shift();
|
|
215
|
+
this._actions[0]?.init?.();
|
|
216
|
+
}
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
start(isRun) {
|
|
220
|
+
if (this._running || !this._valid || !this._actions.length) {
|
|
221
|
+
return this;
|
|
222
|
+
}
|
|
223
|
+
if (Tween._tweenMap.has(this._target)) {
|
|
224
|
+
const tweens = Tween._tweenMap.get(this._target);
|
|
225
|
+
tweens.push(this);
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
Tween._tweenMap.set(this._target, [this]);
|
|
229
|
+
}
|
|
230
|
+
this._actions[0].init?.();
|
|
231
|
+
const func = (dt) => {
|
|
232
|
+
this._running = isRun ? isRun() : true;
|
|
233
|
+
this._running && this._tick(dt);
|
|
234
|
+
}
|
|
235
|
+
func.context = this;
|
|
236
|
+
|
|
237
|
+
callbacks.push(func);
|
|
238
|
+
this._running = true;
|
|
239
|
+
return this;
|
|
240
|
+
}
|
|
241
|
+
stop() {
|
|
242
|
+
if (!this._valid) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
this.pause();
|
|
246
|
+
this._valid = false;
|
|
247
|
+
const tweens = Tween._tweenMap.get(this._target);
|
|
248
|
+
if (!tweens) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
const index = tweens.indexOf(this);
|
|
252
|
+
if (index >= 0) {
|
|
253
|
+
tweens.splice(index, 1);
|
|
254
|
+
if (!tweens.length) {
|
|
255
|
+
Tween._tweenMap.delete(this._target);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
pause() {
|
|
260
|
+
if (!this.running) {
|
|
261
|
+
return this;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const index = callbacks.findIndex(callback => {
|
|
265
|
+
return callback.context === this;
|
|
266
|
+
});
|
|
267
|
+
callbacks.splice(index, 1);
|
|
268
|
+
this._running = false;
|
|
269
|
+
return this;
|
|
270
|
+
}
|
|
271
|
+
to(duration, changes, config) {
|
|
272
|
+
let elapsed = 0;
|
|
273
|
+
const values = {};
|
|
274
|
+
const target = this._target;
|
|
275
|
+
this._actions.push({
|
|
276
|
+
callbacks: [],
|
|
277
|
+
update(dt) {
|
|
278
|
+
const keys = Object.keys(changes);
|
|
279
|
+
elapsed = Math.min(elapsed + dt / duration, 1);
|
|
280
|
+
for (let key of keys) {
|
|
281
|
+
let easing = config?.easeing ? easingFuncs[config.easeing] : easingFuncs.linear;
|
|
282
|
+
easing = easing.bind(easingFuncs);
|
|
283
|
+
target[key] = easing(values[key], changes[key], elapsed);
|
|
284
|
+
}
|
|
285
|
+
config?.onUpdate?.(elapsed);
|
|
286
|
+
if (elapsed >= 1) {
|
|
287
|
+
config?.onComplate?.();
|
|
288
|
+
}
|
|
289
|
+
return elapsed < 1;
|
|
290
|
+
},
|
|
291
|
+
init() {
|
|
292
|
+
elapsed = 0;
|
|
293
|
+
const keys = Object.keys(changes);
|
|
294
|
+
for (let k of keys) {
|
|
295
|
+
values[k] = target[k];
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
return this;
|
|
300
|
+
}
|
|
301
|
+
by(duration, changes, config) {
|
|
302
|
+
let elapsed = 0;
|
|
303
|
+
const values = {};
|
|
304
|
+
const target = this._target;
|
|
305
|
+
const oldChanges = { ...changes };
|
|
306
|
+
changes = { ...changes };
|
|
307
|
+
this._actions.push({
|
|
308
|
+
update(dt) {
|
|
309
|
+
const keys = Object.keys(changes);
|
|
310
|
+
elapsed = Math.min(elapsed + dt / duration, 1);
|
|
311
|
+
for (let key of keys) {
|
|
312
|
+
let easing = config?.easeing ? easingFuncs[config.easeing] : easingFuncs.linear;
|
|
313
|
+
easing = easing.bind(easingFuncs);
|
|
314
|
+
target[key] = easing(values[key], changes[key], elapsed);
|
|
315
|
+
}
|
|
316
|
+
config?.onUpdate?.(elapsed);
|
|
317
|
+
if (elapsed >= 1) {
|
|
318
|
+
config?.onComplate?.();
|
|
319
|
+
}
|
|
320
|
+
return elapsed < 1;
|
|
321
|
+
},
|
|
322
|
+
init() {
|
|
323
|
+
elapsed = 0;
|
|
324
|
+
const keys = Object.keys(changes);
|
|
325
|
+
for (let k of keys) {
|
|
326
|
+
values[k] = target[k];
|
|
327
|
+
changes[k] = oldChanges[k] + values[k];
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
callbacks: []
|
|
331
|
+
});
|
|
332
|
+
return this;
|
|
333
|
+
}
|
|
334
|
+
delay(time) {
|
|
335
|
+
let elapsed = 0;
|
|
336
|
+
this._actions.push({
|
|
337
|
+
callbacks: [],
|
|
338
|
+
update(dt) {
|
|
339
|
+
elapsed += dt;
|
|
340
|
+
return elapsed < time;
|
|
341
|
+
},
|
|
342
|
+
init() {
|
|
343
|
+
elapsed = 0;
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
return this;
|
|
347
|
+
}
|
|
348
|
+
then(...tweens) {
|
|
349
|
+
if (!tweens.length) {
|
|
350
|
+
return this;
|
|
351
|
+
}
|
|
352
|
+
tweens = tweens.map(tw => {
|
|
353
|
+
const newTw = new Tween(tw._target);
|
|
354
|
+
newTw._actions = [...tw._actions];
|
|
355
|
+
return newTw;
|
|
356
|
+
});
|
|
357
|
+
let index = 0;
|
|
358
|
+
this._actions.push({
|
|
359
|
+
update(dt) {
|
|
360
|
+
if (!tweens[index]._tick(dt)) {
|
|
361
|
+
index += 1;
|
|
362
|
+
}
|
|
363
|
+
return index < tweens.length;
|
|
364
|
+
},
|
|
365
|
+
init() {
|
|
366
|
+
tweens[0]._actions[0].init?.();
|
|
367
|
+
},
|
|
368
|
+
callbacks: []
|
|
369
|
+
});
|
|
370
|
+
return this;
|
|
371
|
+
}
|
|
372
|
+
parallel(...tweens) {
|
|
373
|
+
if (!tweens.length) {
|
|
374
|
+
return this;
|
|
375
|
+
}
|
|
376
|
+
tweens = tweens.map(tw => {
|
|
377
|
+
const newTw = new Tween(tw._target);
|
|
378
|
+
newTw._actions = [...tw._actions];
|
|
379
|
+
return newTw;
|
|
380
|
+
});
|
|
381
|
+
this._actions.push({
|
|
382
|
+
update(dt) {
|
|
383
|
+
let finish = 0;
|
|
384
|
+
for (let tw of tweens) {
|
|
385
|
+
if (!tw._tick(dt)) {
|
|
386
|
+
finish++;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
return finish < tweens.length;
|
|
390
|
+
},
|
|
391
|
+
init() {
|
|
392
|
+
for (let tw of tweens) {
|
|
393
|
+
tw._actions[0]?.init?.();
|
|
394
|
+
}
|
|
395
|
+
},
|
|
396
|
+
callbacks: [],
|
|
397
|
+
});
|
|
398
|
+
return this;
|
|
399
|
+
}
|
|
400
|
+
repeat(count, ...tweens) {
|
|
401
|
+
for (let i = 0; i < count; i++) {
|
|
402
|
+
this.then(...tweens);
|
|
403
|
+
}
|
|
404
|
+
return this;
|
|
405
|
+
}
|
|
406
|
+
call(fn) {
|
|
407
|
+
const ac = this._actions[this._actions.length - 1];
|
|
408
|
+
if (ac) {
|
|
409
|
+
ac.callbacks.push(fn);
|
|
410
|
+
}
|
|
411
|
+
else {
|
|
412
|
+
fn();
|
|
413
|
+
}
|
|
414
|
+
return this;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
const callbacks = [];
|
|
419
|
+
let prev = Date.now();
|
|
420
|
+
function update() {
|
|
421
|
+
requestAnimationFrame(() => {
|
|
422
|
+
const dt = (Date.now() - prev) / 1000;
|
|
423
|
+
callbacks.forEach(callback => callback(dt));
|
|
424
|
+
prev = Date.now();
|
|
425
|
+
update();
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
update();
|