forked from daybrush/scenejs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patheasing.ts
165 lines (156 loc) · 3.69 KB
/
easing.ts
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
import { between } from "@daybrush/utils";
import { EasingFunction } from "./types";
function cubic(y1: number, y2: number, t: number) {
const t2 = 1 - t;
// Bezier Curve Formula
return t * t * t + 3 * t * t * t2 * y2 + 3 * t * t2 * t2 * y1;
}
function solveFromX(x1: number, x2: number, x: number) {
// x 0 ~ 1
// t 0 ~ 1
let t = x;
let solveX = x;
let dx = 1;
while (Math.abs(dx) > 1 / 1000) {
// 예상 t초에 의한 _x값
solveX = cubic(x1, x2, t);
dx = solveX - x;
// 차이가 미세하면 그 값을 t로 지정
if (Math.abs(dx) < 1 / 1000) {
return t;
}
t -= dx / 2;
}
return t;
}
/**
* @namespace easing
*/
/**
* Cubic Bezier curve.
* @memberof easing
* @func bezier
* @param {number} [x1] - point1's x
* @param {number} [y1] - point1's y
* @param {number} [x2] - point2's x
* @param {number} [y2] - point2's y
* @return {function} the curve function
* @example
import {bezier} from "scenejs";
Scene.bezier(0, 0, 1, 1) // LINEAR
Scene.bezier(0.25, 0.1, 0.25, 1) // EASE
*/
export function bezier(x1: number, y1: number, x2: number, y2: number) {
/*
x = f(t)
calculate inverse function by x
t = f-1(x)
*/
const func: EasingFunction = (x: number) => {
const t = solveFromX(x1, x2, between(x, 0, 1));
return cubic(y1, y2, t);
};
func.easingName = `cubic-bezier(${x1},${y1},${x2},${y2})`;
return func;
}
/**
* Specifies a stepping function
* @see {@link https://www.w3schools.com/cssref/css3_pr_animation-timing-function.asp|CSS3 Timing Function}
* @memberof easing
* @func steps
* @param {number} count - point1's x
* @param {"start" | "end"} postion - point1's y
* @return {function} the curve function
* @example
import {steps} from "scenejs";
Scene.steps(1, "start") // Scene.STEP_START
Scene.steps(1, "end") // Scene.STEP_END
*/
export function steps(count: number, position: "start" | "end") {
const func: EasingFunction = (time: number) => {
const level = 1 / count;
if (time >= 1) {
return 1;
}
return (position === "start" ? level : 0) + Math.floor(time / level) * level;
};
func.easingName = `steps(${count}, ${position})`;
return func;
}
/**
* Equivalent to steps(1, start)
* @memberof easing
* @name STEP_START
* @static
* @type {function}
* @example
import {STEP_START} from "scenejs";
Scene.STEP_START // steps(1, start)
*/
export const STEP_START = /*#__PURE__#*/steps(1, "start");
/**
* Equivalent to steps(1, end)
* @memberof easing
* @name STEP_END
* @static
* @type {function}
* @example
import {STEP_END} from "scenejs";
Scene.STEP_END // steps(1, end)
*/
export const STEP_END = /*#__PURE__#*/steps(1, "end");
/**
* Linear Speed (0, 0, 1, 1)
* @memberof easing
* @name LINEAR
* @static
* @type {function}
* @example
import {LINEAR} from "scenejs";
Scene.LINEAR
*/
export const LINEAR = /*#__PURE__#*/bezier(0, 0, 1, 1);
/**
* Ease Speed (0.25, 0.1, 0.25, 1)
* @memberof easing
* @name EASE
* @static
* @type {function}
* @example
import {EASE} from "scenejs";
Scene.EASE
*/
export const EASE = /*#__PURE__#*/bezier(0.25, 0.1, 0.25, 1);
/**
* Ease In Speed (0.42, 0, 1, 1)
* @memberof easing
* @name EASE_IN
* @static
* @type {function}
* @example
import {EASE_IN} from "scenejs";
Scene.EASE_IN
*/
export const EASE_IN = /*#__PURE__#*/bezier(0.42, 0, 1, 1);
/**
* Ease Out Speed (0, 0, 0.58, 1)
* @memberof easing
* @name EASE_OUT
* @static
* @type {function}
* @example
import {EASE_OUT} from "scenejs";
Scene.EASE_OUT
*/
export const EASE_OUT = /*#__PURE__#*/bezier(0, 0, 0.58, 1);
/**
* Ease In Out Speed (0.42, 0, 0.58, 1)
* @memberof easing
* @name EASE_IN_OUT
* @static
* @type {function}
* @example
import {EASE_IN_OUT} from "scenejs";
Scene.EASE_IN_OUT
*/
export const EASE_IN_OUT = /*#__PURE__#*/bezier(0.42, 0, 0.58, 1);