UNPKG

gsap

Version:

GSAP is a JavaScript library for building high-performance animations that work in **every** major browser. Animate CSS, SVG, canvas, React, Vue, WebGL, colors, strings, motion paths, generic objects...anything JavaScript can touch! No other library deliv

285 lines (246 loc) 9.76 kB
/*! * MotionPathPlugin 3.0.4 * https://greensock.com * * @license Copyright 2008-2019, GreenSock. All rights reserved. * Subject to the terms at https://greensock.com/standard-license or for * Club GreenSock members, the agreement issued with that membership. * @author: Jack Doyle, jack@greensock.com */ /* eslint-disable */ import { getRawPath, cacheRawPathMeasurements, getPositionOnPath, pointsToSegment, flatPointsToSegment, sliceRawPath, stringToRawPath, rawPathToString, transformRawPath, convertToPath as _convertToPath } from "./utils/paths.js"; import { getGlobalMatrix } from "./utils/matrix.js"; var _xProps = ["x", "translateX", "left", "marginLeft"], _yProps = ["y", "translateY", "top", "marginTop"], _DEG2RAD = Math.PI / 180, gsap, PropTween, _getUnit, _toArray, _getGSAP = function _getGSAP() { return gsap || typeof window !== "undefined" && (gsap = window.gsap) && gsap.registerPlugin && gsap; }, _populateSegmentFromArray = function _populateSegmentFromArray(segment, values, property, mode) { //mode: 0 = x but don't fill y yet, 1 = y. var l = values.length, si = mode, i = 0; for (; i < l; i++) { segment[si] = parseFloat(values[i][property]); si += 2; } return segment; }, _getPropNum = function _getPropNum(target, prop, unit) { return parseFloat(target._gsap.get(target, prop, unit || "px")) || 0; }, _relativize = function _relativize(segment) { var x = segment[0], y = segment[1], i; for (i = 2; i < segment.length; i += 2) { x = segment[i] += x; y = segment[i + 1] += y; } }, _segmentToRawPath = function _segmentToRawPath(plugin, segment, target, x, y, slicer, vars) { if (vars.type === "cubic") { segment = [segment]; } else { segment.unshift(_getPropNum(target, x, vars.unitX), y ? _getPropNum(target, y, vars.unitY) : 0); if (vars.relative) { _relativize(segment); } var pointFunc = y ? pointsToSegment : flatPointsToSegment; segment = [pointFunc(segment, vars.curviness)]; } segment = slicer(_align(segment, target, vars)); _addDimensionalPropTween(plugin, target, x, segment, "x", vars.unitX); if (y) { _addDimensionalPropTween(plugin, target, y, segment, "y", vars.unitY); } 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. }, _emptyFunc = function _emptyFunc(v) { return v; }, _align = function _align(rawPath, target, _ref) { var align = _ref.align, matrix = _ref.matrix, offsetX = _ref.offsetX, offsetY = _ref.offsetY; var x, y, tween, targetMatrix, alignTarget, alignPath, alignMatrix, invertedMatrix, tx, ty; if (!rawPath || !rawPath.length) { return getRawPath("M0,0L0,0"); } if (align) { if (align === "self" || (alignTarget = _toArray(align)[0] || target) === target) { x = _getPropNum(target, "x") - rawPath[0][0]; y = _getPropNum(target, "y") - rawPath[0][1]; transformRawPath(rawPath, 1, 0, 0, 1, x, y); } else { tween = gsap.to(target, { xPercent: 0, yPercent: 0, x: 0, y: 0 }).progress(1); //get rid of transforms, otherwise they'll throw off the measurements. targetMatrix = getGlobalMatrix(target); //we cannot use something like getScreenCTM() because of a major bug in Firefox that has existed for years and prevents values from being reported correctly when an ancestor element has transforms applied. Our proprietary getGlobalMatrix() works across all browsers. tween.render(-1).kill(); if (alignTarget.getTotalLength && alignTarget.tagName.toLowerCase() === "path") { //path alignPath = getRawPath(alignTarget); alignMatrix = getGlobalMatrix(alignTarget.parentNode); x = alignPath[0][0]; y = alignPath[0][1]; } else { alignMatrix = getGlobalMatrix(alignTarget); x = 0; y = 0; } tx = alignMatrix.a * x + alignMatrix.c * y + alignMatrix.e - targetMatrix.e; ty = alignMatrix.b * x + alignMatrix.d * y + alignMatrix.f - targetMatrix.f; invertedMatrix = getGlobalMatrix(target.parentNode, true); x = invertedMatrix.a * tx + invertedMatrix.c * ty; y = invertedMatrix.b * tx + invertedMatrix.d * ty; tx = rawPath[0][0]; ty = rawPath[0][1]; alignMatrix.multiply(invertedMatrix); x -= alignMatrix.a * tx + alignMatrix.c * ty; y -= alignMatrix.b * tx + alignMatrix.d * ty; transformRawPath(rawPath, alignMatrix.a, alignMatrix.b, alignMatrix.c, alignMatrix.d, x, y); } } if (matrix) { transformRawPath(rawPath, matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f); } else if (offsetX || offsetY) { transformRawPath(rawPath, 1, 0, 0, 1, offsetX || 0, offsetY || 0); } return rawPath; }, _addDimensionalPropTween = function _addDimensionalPropTween(plugin, target, property, rawPath, pathProperty, forceUnit) { var cache = target._gsap, pt = plugin._pt = new PropTween(plugin._pt, target, property, 0, 0, _emptyFunc, 0, cache.set(target, property, plugin)); pt.u = _getUnit(cache.get(target, property, forceUnit)) || 0; pt.path = rawPath; pt.pp = pathProperty; plugin._props.push(property); }, _sliceModifier = function _sliceModifier(start, end) { return function (rawPath) { return start || end !== 1 ? sliceRawPath(rawPath, start, end) : rawPath; }; }; export var MotionPathPlugin = { version: "3.0.4", name: "motionPath", register: function register(core, Plugin, propTween) { gsap = core; _getUnit = gsap.utils.getUnit; _toArray = gsap.utils.toArray; PropTween = propTween; }, init: function init(target, vars, tween, index, targets) { if (!gsap) { console.warn("Please gsap.registerPlugin(MotionPathPlugin)"); return false; } if (!(typeof vars === "object" && !vars.style) || !vars.path) { vars = { path: vars }; } var rawPaths = [], path = vars.path, firstObj = path[0], autoRotate = vars.autoRotate, slicer = _sliceModifier(vars.start, "end" in vars ? vars.end : 1), rawPath, p, x, y; this.rawPaths = rawPaths; this.target = target; if (this.rotate = autoRotate || autoRotate === 0) { //get the rotational data FIRST so that the setTransform() method is called in the correct order in the render() loop - rotation gets set last. this.rOffset = parseFloat(autoRotate) || 0; this.radians = !!vars.useRadians; this.rProp = vars.rotation || "rotation"; // rotation property this.rSet = target._gsap.set(target, this.rProp, this); // rotation setter this.ru = _getUnit(target._gsap.get(target, this.rProp)) || 0; // rotation units } if (Array.isArray(path) && !("closed" in path) && typeof firstObj !== "number") { for (p in firstObj) { if (~_xProps.indexOf(p)) { x = p; } else if (~_yProps.indexOf(p)) { y = p; } } if (x && y) { //correlated values rawPaths.push(_segmentToRawPath(this, _populateSegmentFromArray(_populateSegmentFromArray([], path, x, 0), path, y, 1), target, vars.x || x, vars.y || y, slicer, vars)); } else { x = y = 0; } for (p in firstObj) { if (p !== x && p !== y) { rawPaths.push(_segmentToRawPath(this, _populateSegmentFromArray([], path, p, 0), target, p, 0, slicer, vars)); } } } else { rawPath = slicer(_align(getRawPath(vars.path), target, vars)); cacheRawPathMeasurements(rawPath, vars.resolution); rawPaths.push(rawPath); _addDimensionalPropTween(this, target, vars.x || "x", rawPath, "x", vars.unitX || "px"); _addDimensionalPropTween(this, target, vars.y || "y", rawPath, "y", vars.unitY || "px"); } }, render: function render(ratio, data) { var rawPaths = data.rawPaths, i = rawPaths.length, pt = data._pt; if (ratio > 1) { ratio = 1; } else if (ratio < 0) { ratio = 0; } while (i--) { getPositionOnPath(rawPaths[i], ratio, !i && data.rotate, rawPaths[i]); } while (pt) { pt.set(pt.t, pt.p, pt.path[pt.pp] + pt.u, pt.d, ratio); pt = pt._next; } if (data.rotate) { data.rSet(data.target, data.rProp, rawPaths[0].angle * (data.radians ? _DEG2RAD : 1) + data.rOffset + data.ru, data, ratio); } }, getLength: function getLength(path) { return cacheRawPathMeasurements(getRawPath(path)).totalLength; }, sliceRawPath: sliceRawPath, getRawPath: getRawPath, pointsToSegment: pointsToSegment, stringToRawPath: stringToRawPath, rawPathToString: rawPathToString, transformRawPath: transformRawPath, convertToPath: function convertToPath(targets, swap) { return _toArray(targets).map(function (target) { return _convertToPath(target, swap !== false); }); }, getGlobalMatrix: getGlobalMatrix, getPositionOnPath: getPositionOnPath, cacheRawPathMeasurements: cacheRawPathMeasurements, arrayToRawPath: function arrayToRawPath(value, vars) { vars = vars || {}; var segment = _populateSegmentFromArray(_populateSegmentFromArray([], value, vars.x || "x", 0), value, vars.y || "y", 1); if (vars.relative) { _relativize(segment); } return [vars.type === "cubic" ? segment : pointsToSegment(segment, vars.curviness)]; } }; _getGSAP() && gsap.registerPlugin(MotionPathPlugin); export { MotionPathPlugin as default };