1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | import { stringToRawPath, rawPathToString, transformRawPath } from "./utils/paths.js";
|
13 |
|
14 | var gsap,
|
15 | _coreInitted,
|
16 | _getGSAP = function _getGSAP() {
|
17 | return gsap || typeof window !== "undefined" && (gsap = window.gsap) && gsap.registerPlugin && gsap;
|
18 | },
|
19 | _initCore = function _initCore() {
|
20 | gsap = _getGSAP();
|
21 |
|
22 | if (gsap) {
|
23 | gsap.registerEase("_CE", CustomEase.create);
|
24 | _coreInitted = 1;
|
25 | } else {
|
26 | console.warn("Please gsap.registerPlugin(CustomEase)");
|
27 | }
|
28 | },
|
29 | _bigNum = 1e20,
|
30 | _round = function _round(value) {
|
31 | return ~~(value * 1000 + (value < 0 ? -.5 : .5)) / 1000;
|
32 | },
|
33 | _bonusValidated = 1,
|
34 |
|
35 | _numExp = /[-+=\.]*\d+[\.e\-\+]*\d*[e\-\+]*\d*/gi,
|
36 |
|
37 | _needsParsingExp = /[cLlsSaAhHvVtTqQ]/g,
|
38 | _findMinimum = function _findMinimum(values) {
|
39 | var l = values.length,
|
40 | min = _bigNum,
|
41 | i;
|
42 |
|
43 | for (i = 1; i < l; i += 6) {
|
44 | +values[i] < min && (min = +values[i]);
|
45 | }
|
46 |
|
47 | return min;
|
48 | },
|
49 |
|
50 | _normalize = function _normalize(values, height, originY) {
|
51 | if (!originY && originY !== 0) {
|
52 | originY = Math.max(+values[values.length - 1], +values[1]);
|
53 | }
|
54 |
|
55 | var tx = +values[0] * -1,
|
56 | ty = -originY,
|
57 | l = values.length,
|
58 | sx = 1 / (+values[l - 2] + tx),
|
59 | sy = -height || (Math.abs(+values[l - 1] - +values[1]) < 0.01 * (+values[l - 2] - +values[0]) ? _findMinimum(values) + ty : +values[l - 1] + ty),
|
60 | i;
|
61 |
|
62 | if (sy) {
|
63 |
|
64 | sy = 1 / sy;
|
65 | } else {
|
66 |
|
67 | sy = -sx;
|
68 | }
|
69 |
|
70 | for (i = 0; i < l; i += 2) {
|
71 | values[i] = (+values[i] + tx) * sx;
|
72 | values[i + 1] = (+values[i + 1] + ty) * sy;
|
73 | }
|
74 | },
|
75 |
|
76 | _bezierToPoints = function _bezierToPoints(x1, y1, x2, y2, x3, y3, x4, y4, threshold, points, index) {
|
77 | var x12 = (x1 + x2) / 2,
|
78 | y12 = (y1 + y2) / 2,
|
79 | x23 = (x2 + x3) / 2,
|
80 | y23 = (y2 + y3) / 2,
|
81 | x34 = (x3 + x4) / 2,
|
82 | y34 = (y3 + y4) / 2,
|
83 | x123 = (x12 + x23) / 2,
|
84 | y123 = (y12 + y23) / 2,
|
85 | x234 = (x23 + x34) / 2,
|
86 | y234 = (y23 + y34) / 2,
|
87 | x1234 = (x123 + x234) / 2,
|
88 | y1234 = (y123 + y234) / 2,
|
89 | dx = x4 - x1,
|
90 | dy = y4 - y1,
|
91 | d2 = Math.abs((x2 - x4) * dy - (y2 - y4) * dx),
|
92 | d3 = Math.abs((x3 - x4) * dy - (y3 - y4) * dx),
|
93 | length;
|
94 |
|
95 | if (!points) {
|
96 | points = [{
|
97 | x: x1,
|
98 | y: y1
|
99 | }, {
|
100 | x: x4,
|
101 | y: y4
|
102 | }];
|
103 | index = 1;
|
104 | }
|
105 |
|
106 | points.splice(index || points.length - 1, 0, {
|
107 | x: x1234,
|
108 | y: y1234
|
109 | });
|
110 |
|
111 | if ((d2 + d3) * (d2 + d3) > threshold * (dx * dx + dy * dy)) {
|
112 | length = points.length;
|
113 |
|
114 | _bezierToPoints(x1, y1, x12, y12, x123, y123, x1234, y1234, threshold, points, index);
|
115 |
|
116 | _bezierToPoints(x1234, y1234, x234, y234, x34, y34, x4, y4, threshold, points, index + 1 + (points.length - length));
|
117 | }
|
118 |
|
119 | return points;
|
120 | };
|
121 |
|
122 | export var CustomEase = function () {
|
123 | function CustomEase(id, data, config) {
|
124 | _coreInitted || _initCore();
|
125 | this.id = id;
|
126 | _bonusValidated && this.setData(data, config);
|
127 | }
|
128 |
|
129 | var _proto = CustomEase.prototype;
|
130 |
|
131 | _proto.setData = function setData(data, config) {
|
132 | config = config || {};
|
133 | data = data || "0,0,1,1";
|
134 | var values = data.match(_numExp),
|
135 | closest = 1,
|
136 | points = [],
|
137 | lookup = [],
|
138 | precision = config.precision || 1,
|
139 | fast = precision <= 1,
|
140 | l,
|
141 | a1,
|
142 | a2,
|
143 | i,
|
144 | inc,
|
145 | j,
|
146 | point,
|
147 | prevPoint,
|
148 | p;
|
149 | this.data = data;
|
150 |
|
151 | if (_needsParsingExp.test(data) || ~data.indexOf("M") && data.indexOf("C") < 0) {
|
152 | values = stringToRawPath(data)[0];
|
153 | }
|
154 |
|
155 | l = values.length;
|
156 |
|
157 | if (l === 4) {
|
158 | values.unshift(0, 0);
|
159 | values.push(1, 1);
|
160 | l = 8;
|
161 | } else if ((l - 2) % 6) {
|
162 | throw "Invalid CustomEase";
|
163 | }
|
164 |
|
165 | if (+values[0] !== 0 || +values[l - 2] !== 1) {
|
166 | _normalize(values, config.height, config.originY);
|
167 | }
|
168 |
|
169 | this.segment = values;
|
170 |
|
171 | for (i = 2; i < l; i += 6) {
|
172 | a1 = {
|
173 | x: +values[i - 2],
|
174 | y: +values[i - 1]
|
175 | };
|
176 | a2 = {
|
177 | x: +values[i + 4],
|
178 | y: +values[i + 5]
|
179 | };
|
180 | points.push(a1, a2);
|
181 |
|
182 | _bezierToPoints(a1.x, a1.y, +values[i], +values[i + 1], +values[i + 2], +values[i + 3], a2.x, a2.y, 1 / (precision * 200000), points, points.length - 1);
|
183 | }
|
184 |
|
185 | l = points.length;
|
186 |
|
187 | for (i = 0; i < l; i++) {
|
188 | point = points[i];
|
189 | prevPoint = points[i - 1] || point;
|
190 |
|
191 | if ((point.x > prevPoint.x || prevPoint.y !== point.y && prevPoint.x === point.x || point === prevPoint) && point.x <= 1) {
|
192 |
|
193 | prevPoint.cx = point.x - prevPoint.x;
|
194 |
|
195 | prevPoint.cy = point.y - prevPoint.y;
|
196 | prevPoint.n = point;
|
197 | prevPoint.nx = point.x;
|
198 |
|
199 | if (fast && i > 1 && Math.abs(prevPoint.cy / prevPoint.cx - points[i - 2].cy / points[i - 2].cx) > 2) {
|
200 |
|
201 | fast = 0;
|
202 | }
|
203 |
|
204 | if (prevPoint.cx < closest) {
|
205 | if (!prevPoint.cx) {
|
206 | prevPoint.cx = 0.001;
|
207 |
|
208 | if (i === l - 1) {
|
209 |
|
210 | prevPoint.x -= 0.001;
|
211 | closest = Math.min(closest, 0.001);
|
212 | fast = 0;
|
213 | }
|
214 | } else {
|
215 | closest = prevPoint.cx;
|
216 | }
|
217 | }
|
218 | } else {
|
219 | points.splice(i--, 1);
|
220 | l--;
|
221 | }
|
222 | }
|
223 |
|
224 | l = 1 / closest + 1 | 0;
|
225 | inc = 1 / l;
|
226 | j = 0;
|
227 | point = points[0];
|
228 |
|
229 | if (fast) {
|
230 | for (i = 0; i < l; i++) {
|
231 |
|
232 | p = i * inc;
|
233 |
|
234 | if (point.nx < p) {
|
235 | point = points[++j];
|
236 | }
|
237 |
|
238 | a1 = point.y + (p - point.x) / point.cx * point.cy;
|
239 | lookup[i] = {
|
240 | x: p,
|
241 | cx: inc,
|
242 | y: a1,
|
243 | cy: 0,
|
244 | nx: 9
|
245 | };
|
246 |
|
247 | if (i) {
|
248 | lookup[i - 1].cy = a1 - lookup[i - 1].y;
|
249 | }
|
250 | }
|
251 |
|
252 | lookup[l - 1].cy = points[points.length - 1].y - a1;
|
253 | } else {
|
254 |
|
255 | for (i = 0; i < l; i++) {
|
256 |
|
257 | if (point.nx < i * inc) {
|
258 | point = points[++j];
|
259 | }
|
260 |
|
261 | lookup[i] = point;
|
262 | }
|
263 |
|
264 | if (j < points.length - 1) {
|
265 | lookup[i - 1] = points[points.length - 2];
|
266 | }
|
267 | }
|
268 |
|
269 |
|
270 | this.ease = function (p) {
|
271 | var point = lookup[p * l | 0] || lookup[l - 1];
|
272 |
|
273 | if (point.nx < p) {
|
274 | point = point.n;
|
275 | }
|
276 |
|
277 | return point.y + (p - point.x) / point.cx * point.cy;
|
278 | };
|
279 |
|
280 | this.ease.custom = this;
|
281 | this.id && gsap && gsap.registerEase(this.id, this.ease);
|
282 | return this;
|
283 | };
|
284 |
|
285 | _proto.getSVGData = function getSVGData(config) {
|
286 | return CustomEase.getSVGData(this, config);
|
287 | };
|
288 |
|
289 | CustomEase.create = function create(id, data, config) {
|
290 | return new CustomEase(id, data, config).ease;
|
291 | };
|
292 |
|
293 | CustomEase.register = function register(core) {
|
294 | gsap = core;
|
295 |
|
296 | _initCore();
|
297 | };
|
298 |
|
299 | CustomEase.get = function get(id) {
|
300 | return gsap.parseEase(id);
|
301 | };
|
302 |
|
303 | CustomEase.getSVGData = function getSVGData(ease, config) {
|
304 | config = config || {};
|
305 | var width = config.width || 100,
|
306 | height = config.height || 100,
|
307 | x = config.x || 0,
|
308 | y = (config.y || 0) + height,
|
309 | e = gsap.utils.toArray(config.path)[0],
|
310 | a,
|
311 | slope,
|
312 | i,
|
313 | inc,
|
314 | tx,
|
315 | ty,
|
316 | precision,
|
317 | threshold,
|
318 | prevX,
|
319 | prevY;
|
320 |
|
321 | if (config.invert) {
|
322 | height = -height;
|
323 | y = 0;
|
324 | }
|
325 |
|
326 | if (typeof ease === "string") {
|
327 | ease = gsap.parseEase(ease);
|
328 | }
|
329 |
|
330 | if (ease.custom) {
|
331 | ease = ease.custom;
|
332 | }
|
333 |
|
334 | if (ease instanceof CustomEase) {
|
335 | a = rawPathToString(transformRawPath([ease.segment], width, 0, 0, -height, x, y));
|
336 | } else {
|
337 | a = [x, y];
|
338 | precision = Math.max(5, (config.precision || 1) * 200);
|
339 | inc = 1 / precision;
|
340 | precision += 2;
|
341 | threshold = 5 / precision;
|
342 | prevX = _round(x + inc * width);
|
343 | prevY = _round(y + ease(inc) * -height);
|
344 | slope = (prevY - y) / (prevX - x);
|
345 |
|
346 | for (i = 2; i < precision; i++) {
|
347 | tx = _round(x + i * inc * width);
|
348 | ty = _round(y + ease(i * inc) * -height);
|
349 |
|
350 | if (Math.abs((ty - prevY) / (tx - prevX) - slope) > threshold || i === precision - 1) {
|
351 |
|
352 | a.push(prevX, prevY);
|
353 | slope = (ty - prevY) / (tx - prevX);
|
354 | }
|
355 |
|
356 | prevX = tx;
|
357 | prevY = ty;
|
358 | }
|
359 |
|
360 | a = "M" + a.join(",");
|
361 | }
|
362 |
|
363 | e && e.setAttribute("d", a);
|
364 | return a;
|
365 | };
|
366 |
|
367 | return CustomEase;
|
368 | }();
|
369 | _getGSAP() && gsap.registerPlugin(CustomEase);
|
370 | CustomEase.version = "3.10.3";
|
371 | export { CustomEase as default }; |
\ | No newline at end of file |