1 | function easeInOutSin(time) {
|
2 | return (1 + Math.sin(Math.PI * time - Math.PI / 2)) / 2;
|
3 | }
|
4 |
|
5 | export default function animate(property, element, to, options = {}, cb = () => {}) {
|
6 | const {
|
7 | ease = easeInOutSin,
|
8 | duration = 300
|
9 |
|
10 | } = options;
|
11 | let start = null;
|
12 | const from = element[property];
|
13 | let cancelled = false;
|
14 |
|
15 | const cancel = () => {
|
16 | cancelled = true;
|
17 | };
|
18 |
|
19 | const step = timestamp => {
|
20 | if (cancelled) {
|
21 | cb(new Error('Animation cancelled'));
|
22 | return;
|
23 | }
|
24 |
|
25 | if (start === null) {
|
26 | start = timestamp;
|
27 | }
|
28 |
|
29 | const time = Math.min(1, (timestamp - start) / duration);
|
30 | element[property] = ease(time) * (to - from) + from;
|
31 |
|
32 | if (time >= 1) {
|
33 | requestAnimationFrame(() => {
|
34 | cb(null);
|
35 | });
|
36 | return;
|
37 | }
|
38 |
|
39 | requestAnimationFrame(step);
|
40 | };
|
41 |
|
42 | if (from === to) {
|
43 | cb(new Error('Element already at target position'));
|
44 | return cancel;
|
45 | }
|
46 |
|
47 | requestAnimationFrame(step);
|
48 | return cancel;
|
49 | } |
\ | No newline at end of file |