UNPKG

11.5 kBJavaScriptView Raw
1/*!
2 * MotionPathPlugin 3.4.2
3 * https://greensock.com
4 *
5 * @license Copyright 2008-2020, GreenSock. All rights reserved.
6 * Subject to the terms at https://greensock.com/standard-license or for
7 * Club GreenSock members, the agreement issued with that membership.
8 * @author: Jack Doyle, jack@greensock.com
9*/
10
11/* eslint-disable */
12import { getRawPath, cacheRawPathMeasurements, getPositionOnPath, pointsToSegment, flatPointsToSegment, sliceRawPath, stringToRawPath, rawPathToString, transformRawPath, convertToPath as _convertToPath } from "./utils/paths.js";
13import { getGlobalMatrix } from "./utils/matrix.js";
14
15var _xProps = ["x", "translateX", "left", "marginLeft"],
16 _yProps = ["y", "translateY", "top", "marginTop"],
17 _DEG2RAD = Math.PI / 180,
18 gsap,
19 PropTween,
20 _getUnit,
21 _toArray,
22 _getGSAP = function _getGSAP() {
23 return gsap || typeof window !== "undefined" && (gsap = window.gsap) && gsap.registerPlugin && gsap;
24},
25 _populateSegmentFromArray = function _populateSegmentFromArray(segment, values, property, mode) {
26 //mode: 0 = x but don't fill y yet, 1 = y, 2 = x and fill y with 0.
27 var l = values.length,
28 si = mode === 2 ? 0 : mode,
29 i = 0;
30
31 for (; i < l; i++) {
32 segment[si] = parseFloat(values[i][property]);
33 mode === 2 && (segment[si + 1] = 0);
34 si += 2;
35 }
36
37 return segment;
38},
39 _getPropNum = function _getPropNum(target, prop, unit) {
40 return parseFloat(target._gsap.get(target, prop, unit || "px")) || 0;
41},
42 _relativize = function _relativize(segment) {
43 var x = segment[0],
44 y = segment[1],
45 i;
46
47 for (i = 2; i < segment.length; i += 2) {
48 x = segment[i] += x;
49 y = segment[i + 1] += y;
50 }
51},
52 _segmentToRawPath = function _segmentToRawPath(plugin, segment, target, x, y, slicer, vars) {
53 if (vars.type === "cubic") {
54 segment = [segment];
55 } else {
56 segment.unshift(_getPropNum(target, x, vars.unitX), y ? _getPropNum(target, y, vars.unitY) : 0);
57 vars.relative && _relativize(segment);
58 var pointFunc = y ? pointsToSegment : flatPointsToSegment;
59 segment = [pointFunc(segment, vars.curviness)];
60 }
61
62 segment = slicer(_align(segment, target, vars));
63
64 _addDimensionalPropTween(plugin, target, x, segment, "x", vars.unitX);
65
66 y && _addDimensionalPropTween(plugin, target, y, segment, "y", vars.unitY);
67 return cacheRawPathMeasurements(segment, vars.resolution || (vars.curviness === 0 ? 20 : 12)); //when curviness is 0, it creates control points right on top of the anchors which makes it more sensitive to resolution, thus we change the default accordingly.
68},
69 _emptyFunc = function _emptyFunc(v) {
70 return v;
71},
72 _numExp = /[-+\.]*\d+[\.e\-\+]*\d*[e\-\+]*\d*/g,
73 _originToPoint = function _originToPoint(element, origin, parentMatrix) {
74 // origin is an array of normalized values (0-1) in relation to the width/height, so [0.5, 0.5] would be the center. It can also be "auto" in which case it will be the top left unless it's a <path>, when it will start at the beginning of the path itself.
75 var m = getGlobalMatrix(element),
76 svg,
77 x,
78 y;
79
80 if ((element.tagName + "").toLowerCase() === "svg") {
81 svg = element.viewBox.baseVal;
82 x = svg.x;
83 y = svg.y;
84 svg.width || (svg = {
85 width: +element.getAttribute("width"),
86 height: +element.getAttribute("height")
87 });
88 } else {
89 svg = origin && element.getBBox && element.getBBox();
90 x = y = 0;
91 }
92
93 if (origin && origin !== "auto") {
94 x += origin.push ? origin[0] * (svg ? svg.width : element.offsetWidth || 0) : origin.x;
95 y += origin.push ? origin[1] * (svg ? svg.height : element.offsetHeight || 0) : origin.y;
96 }
97
98 return parentMatrix.apply(x || y ? m.apply({
99 x: x,
100 y: y
101 }) : {
102 x: m.e,
103 y: m.f
104 });
105},
106 _getAlignMatrix = function _getAlignMatrix(fromElement, toElement, fromOrigin, toOrigin) {
107 var parentMatrix = getGlobalMatrix(fromElement.parentNode, true, true),
108 m = parentMatrix.clone().multiply(getGlobalMatrix(toElement)),
109 fromPoint = _originToPoint(fromElement, fromOrigin, parentMatrix),
110 _originToPoint2 = _originToPoint(toElement, toOrigin, parentMatrix),
111 x = _originToPoint2.x,
112 y = _originToPoint2.y,
113 p;
114
115 m.e = m.f = 0;
116
117 if (toOrigin === "auto" && toElement.getTotalLength && toElement.tagName.toLowerCase() === "path") {
118 p = toElement.getAttribute("d").match(_numExp) || [];
119 p = m.apply({
120 x: +p[0],
121 y: +p[1]
122 });
123 x += p.x;
124 y += p.y;
125 }
126
127 if (p || toElement.getBBox && fromElement.getBBox && toElement.ownerSVGElement === fromElement.ownerSVGElement) {
128 p = m.apply(toElement.getBBox());
129 x -= p.x;
130 y -= p.y;
131 }
132
133 m.e = x - fromPoint.x;
134 m.f = y - fromPoint.y;
135 return m;
136},
137 _align = function _align(rawPath, target, _ref) {
138 var align = _ref.align,
139 matrix = _ref.matrix,
140 offsetX = _ref.offsetX,
141 offsetY = _ref.offsetY,
142 alignOrigin = _ref.alignOrigin;
143
144 var x = rawPath[0][0],
145 y = rawPath[0][1],
146 curX = _getPropNum(target, "x"),
147 curY = _getPropNum(target, "y"),
148 alignTarget,
149 m,
150 p;
151
152 if (!rawPath || !rawPath.length) {
153 return getRawPath("M0,0L0,0");
154 }
155
156 if (align) {
157 if (align === "self" || (alignTarget = _toArray(align)[0] || target) === target) {
158 transformRawPath(rawPath, 1, 0, 0, 1, curX - x, curY - y);
159 } else {
160 if (alignOrigin && alignOrigin[2] !== false) {
161 gsap.set(target, {
162 transformOrigin: alignOrigin[0] * 100 + "% " + alignOrigin[1] * 100 + "%"
163 });
164 } else {
165 alignOrigin = [_getPropNum(target, "xPercent") / -100, _getPropNum(target, "yPercent") / -100];
166 }
167
168 m = _getAlignMatrix(target, alignTarget, alignOrigin, "auto");
169 p = m.apply({
170 x: x,
171 y: y
172 });
173 transformRawPath(rawPath, m.a, m.b, m.c, m.d, curX + m.e - (p.x - m.e), curY + m.f - (p.y - m.f));
174 }
175 }
176
177 if (matrix) {
178 transformRawPath(rawPath, matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f);
179 } else if (offsetX || offsetY) {
180 transformRawPath(rawPath, 1, 0, 0, 1, offsetX || 0, offsetY || 0);
181 }
182
183 return rawPath;
184},
185 _addDimensionalPropTween = function _addDimensionalPropTween(plugin, target, property, rawPath, pathProperty, forceUnit) {
186 var cache = target._gsap,
187 harness = cache.harness,
188 alias = harness && harness.aliases && harness.aliases[property],
189 prop = alias && alias.indexOf(",") < 0 ? alias : property,
190 pt = plugin._pt = new PropTween(plugin._pt, target, prop, 0, 0, _emptyFunc, 0, cache.set(target, prop, plugin));
191 pt.u = _getUnit(cache.get(target, prop, forceUnit)) || 0;
192 pt.path = rawPath;
193 pt.pp = pathProperty;
194
195 plugin._props.push(prop);
196},
197 _sliceModifier = function _sliceModifier(start, end) {
198 return function (rawPath) {
199 return start || end !== 1 ? sliceRawPath(rawPath, start, end) : rawPath;
200 };
201};
202
203export var MotionPathPlugin = {
204 version: "3.4.2",
205 name: "motionPath",
206 register: function register(core, Plugin, propTween) {
207 gsap = core;
208 _getUnit = gsap.utils.getUnit;
209 _toArray = gsap.utils.toArray;
210 PropTween = propTween;
211 },
212 init: function init(target, vars) {
213 if (!gsap) {
214 console.warn("Please gsap.registerPlugin(MotionPathPlugin)");
215 return false;
216 }
217
218 if (!(typeof vars === "object" && !vars.style) || !vars.path) {
219 vars = {
220 path: vars
221 };
222 }
223
224 var rawPaths = [],
225 path = vars.path,
226 firstObj = path[0],
227 autoRotate = vars.autoRotate,
228 slicer = _sliceModifier(vars.start, "end" in vars ? vars.end : 1),
229 rawPath,
230 p,
231 x,
232 y;
233
234 this.rawPaths = rawPaths;
235 this.target = target;
236
237 if (this.rotate = autoRotate || autoRotate === 0) {
238 //get the rotational data FIRST so that the setTransform() method is called in the correct order in the render() loop - rotation gets set last.
239 this.rOffset = parseFloat(autoRotate) || 0;
240 this.radians = !!vars.useRadians;
241 this.rProp = vars.rotation || "rotation"; // rotation property
242
243 this.rSet = target._gsap.set(target, this.rProp, this); // rotation setter
244
245 this.ru = _getUnit(target._gsap.get(target, this.rProp)) || 0; // rotation units
246 }
247
248 if (Array.isArray(path) && !("closed" in path) && typeof firstObj !== "number") {
249 for (p in firstObj) {
250 if (~_xProps.indexOf(p)) {
251 x = p;
252 } else if (~_yProps.indexOf(p)) {
253 y = p;
254 }
255 }
256
257 if (x && y) {
258 //correlated values
259 rawPaths.push(_segmentToRawPath(this, _populateSegmentFromArray(_populateSegmentFromArray([], path, x, 0), path, y, 1), target, vars.x || x, vars.y || y, slicer, vars));
260 } else {
261 x = y = 0;
262 }
263
264 for (p in firstObj) {
265 if (p !== x && p !== y) {
266 rawPaths.push(_segmentToRawPath(this, _populateSegmentFromArray([], path, p, 2), target, p, 0, slicer, vars));
267 }
268 }
269 } else {
270 rawPath = slicer(_align(getRawPath(vars.path), target, vars));
271 cacheRawPathMeasurements(rawPath, vars.resolution);
272 rawPaths.push(rawPath);
273
274 _addDimensionalPropTween(this, target, vars.x || "x", rawPath, "x", vars.unitX || "px");
275
276 _addDimensionalPropTween(this, target, vars.y || "y", rawPath, "y", vars.unitY || "px");
277 }
278 },
279 render: function render(ratio, data) {
280 var rawPaths = data.rawPaths,
281 i = rawPaths.length,
282 pt = data._pt;
283
284 if (ratio > 1) {
285 ratio = 1;
286 } else if (ratio < 0) {
287 ratio = 0;
288 }
289
290 while (i--) {
291 getPositionOnPath(rawPaths[i], ratio, !i && data.rotate, rawPaths[i]);
292 }
293
294 while (pt) {
295 pt.set(pt.t, pt.p, pt.path[pt.pp] + pt.u, pt.d, ratio);
296 pt = pt._next;
297 }
298
299 data.rotate && data.rSet(data.target, data.rProp, rawPaths[0].angle * (data.radians ? _DEG2RAD : 1) + data.rOffset + data.ru, data, ratio);
300 },
301 getLength: function getLength(path) {
302 return cacheRawPathMeasurements(getRawPath(path)).totalLength;
303 },
304 sliceRawPath: sliceRawPath,
305 getRawPath: getRawPath,
306 pointsToSegment: pointsToSegment,
307 stringToRawPath: stringToRawPath,
308 rawPathToString: rawPathToString,
309 transformRawPath: transformRawPath,
310 getGlobalMatrix: getGlobalMatrix,
311 getPositionOnPath: getPositionOnPath,
312 cacheRawPathMeasurements: cacheRawPathMeasurements,
313 convertToPath: function convertToPath(targets, swap) {
314 return _toArray(targets).map(function (target) {
315 return _convertToPath(target, swap !== false);
316 });
317 },
318 convertCoordinates: function convertCoordinates(fromElement, toElement, point) {
319 var m = getGlobalMatrix(toElement, true, true).multiply(getGlobalMatrix(fromElement));
320 return point ? m.apply(point) : m;
321 },
322 getAlignMatrix: _getAlignMatrix,
323 getRelativePosition: function getRelativePosition(fromElement, toElement, fromOrigin, toOrigin) {
324 var m = _getAlignMatrix(fromElement, toElement, fromOrigin, toOrigin);
325
326 return {
327 x: m.e,
328 y: m.f
329 };
330 },
331 arrayToRawPath: function arrayToRawPath(value, vars) {
332 vars = vars || {};
333
334 var segment = _populateSegmentFromArray(_populateSegmentFromArray([], value, vars.x || "x", 0), value, vars.y || "y", 1);
335
336 vars.relative && _relativize(segment);
337 return [vars.type === "cubic" ? segment : pointsToSegment(segment, vars.curviness)];
338 }
339};
340_getGSAP() && gsap.registerPlugin(MotionPathPlugin);
341export { MotionPathPlugin as default };
\No newline at end of file