UNPKG

gsap

Version:

GSAP is a framework-agnostic JavaScript animation library that turns developers into animation superheroes. Build high-performance animations that work in **every** major browser. Animate CSS, SVG, canvas, React, Vue, WebGL, colors, strings, motion paths,

1,723 lines (1,481 loc) 56 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = global || self, factory(global.window = global.window || {})); }(this, (function (exports) { 'use strict'; function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } var _svgPathExp = /[achlmqstvz]|(-?\d*\.?\d*(?:e[\-+]?\d+)?)[0-9]/ig, _numbersExp = /(?:(-)?\d*\.?\d*(?:e[\-+]?\d+)?)[0-9]/ig, _scientific = /[\+\-]?\d*\.?\d+e[\+\-]?\d+/ig, _selectorExp = /(^[#\.][a-z]|[a-y][a-z])/i, _DEG2RAD = Math.PI / 180, _sin = Math.sin, _cos = Math.cos, _abs = Math.abs, _sqrt = Math.sqrt, _atan2 = Math.atan2, _largeNum = 1e8, _isString = function _isString(value) { return typeof value === "string"; }, _isNumber = function _isNumber(value) { return typeof value === "number"; }, _roundingNum = 1e5, _round = function _round(value) { return Math.round(value * _roundingNum) / _roundingNum || 0; }, _segmentIsClosed = function _segmentIsClosed(segment) { return segment.closed = Math.abs(segment[0] - segment[segment.length - 2]) < 0.001 && Math.abs(segment[1] - segment[segment.length - 1]) < 0.001; }, _getSampleIndex = function _getSampleIndex(samples, length, progress) { var l = samples.length, i = ~~(progress * l); if (samples[i] > length) { while (--i && samples[i] > length) {} i < 0 && (i = 0); } else { while (samples[++i] < length && i < l) {} } return i < l ? i : l - 1; }; function getRawPath(value) { value = _isString(value) && _selectorExp.test(value) ? document.querySelector(value) || value : value; var e = value.getAttribute ? value : 0, rawPath; if (e && (value = value.getAttribute("d"))) { if (!e._gsPath) { e._gsPath = {}; } rawPath = e._gsPath[value]; return rawPath && !rawPath._dirty ? rawPath : e._gsPath[value] = stringToRawPath(value); } return !value ? console.warn("Expecting a <path> element or an SVG path data string") : _isString(value) ? stringToRawPath(value) : _isNumber(value[0]) ? [value] : value; } function reverseSegment(segment) { var i = 0, y; segment.reverse(); for (; i < segment.length; i += 2) { y = segment[i]; segment[i] = segment[i + 1]; segment[i + 1] = y; } segment.reversed = !segment.reversed; } var _createPath = function _createPath(e, ignore) { var path = document.createElementNS("http://www.w3.org/2000/svg", "path"), attr = [].slice.call(e.attributes), i = attr.length, name; ignore = "," + ignore + ","; while (--i > -1) { name = attr[i].nodeName.toLowerCase(); if (ignore.indexOf("," + name + ",") < 0) { path.setAttributeNS(null, name, attr[i].nodeValue); } } return path; }, _typeAttrs = { rect: "rx,ry,x,y,width,height", circle: "r,cx,cy", ellipse: "rx,ry,cx,cy", line: "x1,x2,y1,y2" }, _attrToObj = function _attrToObj(e, attrs) { var props = attrs ? attrs.split(",") : [], obj = {}, i = props.length; while (--i > -1) { obj[props[i]] = +e.getAttribute(props[i]) || 0; } return obj; }; function convertToPath(element, swap) { var type = element.tagName.toLowerCase(), circ = 0.552284749831, data, x, y, r, ry, path, rcirc, rycirc, points, w, h, x2, x3, x4, x5, x6, y2, y3, y4, y5, y6, attr; if (type === "path" || !element.getBBox) { return element; } path = _createPath(element, "x,y,width,height,cx,cy,rx,ry,r,x1,x2,y1,y2,points"); attr = _attrToObj(element, _typeAttrs[type]); if (type === "rect") { r = attr.rx; ry = attr.ry || r; x = attr.x; y = attr.y; w = attr.width - r * 2; h = attr.height - ry * 2; if (r || ry) { x2 = x + r * (1 - circ); x3 = x + r; x4 = x3 + w; x5 = x4 + r * circ; x6 = x4 + r; y2 = y + ry * (1 - circ); y3 = y + ry; y4 = y3 + h; y5 = y4 + ry * circ; y6 = y4 + ry; data = "M" + x6 + "," + y3 + " V" + y4 + " C" + [x6, y5, x5, y6, x4, y6, x4 - (x4 - x3) / 3, y6, x3 + (x4 - x3) / 3, y6, x3, y6, x2, y6, x, y5, x, y4, x, y4 - (y4 - y3) / 3, x, y3 + (y4 - y3) / 3, x, y3, x, y2, x2, y, x3, y, x3 + (x4 - x3) / 3, y, x4 - (x4 - x3) / 3, y, x4, y, x5, y, x6, y2, x6, y3].join(",") + "z"; } else { data = "M" + (x + w) + "," + y + " v" + h + " h" + -w + " v" + -h + " h" + w + "z"; } } else if (type === "circle" || type === "ellipse") { if (type === "circle") { r = ry = attr.r; rycirc = r * circ; } else { r = attr.rx; ry = attr.ry; rycirc = ry * circ; } x = attr.cx; y = attr.cy; rcirc = r * circ; data = "M" + (x + r) + "," + y + " C" + [x + r, y + rycirc, x + rcirc, y + ry, x, y + ry, x - rcirc, y + ry, x - r, y + rycirc, x - r, y, x - r, y - rycirc, x - rcirc, y - ry, x, y - ry, x + rcirc, y - ry, x + r, y - rycirc, x + r, y].join(",") + "z"; } else if (type === "line") { data = "M" + attr.x1 + "," + attr.y1 + " L" + attr.x2 + "," + attr.y2; } else if (type === "polyline" || type === "polygon") { points = (element.getAttribute("points") + "").match(_numbersExp) || []; x = points.shift(); y = points.shift(); data = "M" + x + "," + y + " L" + points.join(","); if (type === "polygon") { data += "," + x + "," + y + "z"; } } path.setAttribute("d", rawPathToString(path._gsRawPath = stringToRawPath(data))); if (swap && element.parentNode) { element.parentNode.insertBefore(path, element); element.parentNode.removeChild(element); } return path; } function measureSegment(segment, startIndex, bezierQty) { startIndex = startIndex || 0; if (!segment.samples) { segment.samples = []; segment.lookup = []; } var resolution = ~~segment.resolution || 12, inc = 1 / resolution, endIndex = bezierQty ? startIndex + bezierQty * 6 + 1 : segment.length, x1 = segment[startIndex], y1 = segment[startIndex + 1], samplesIndex = startIndex ? startIndex / 6 * resolution : 0, samples = segment.samples, lookup = segment.lookup, min = (startIndex ? segment.minLength : _largeNum) || _largeNum, prevLength = samples[samplesIndex + bezierQty * resolution - 1], length = startIndex ? samples[samplesIndex - 1] : 0, i, j, x4, x3, x2, xd, xd1, y4, y3, y2, yd, yd1, inv, t, lengthIndex, l, segLength; samples.length = lookup.length = 0; for (j = startIndex + 2; j < endIndex; j += 6) { x4 = segment[j + 4] - x1; x3 = segment[j + 2] - x1; x2 = segment[j] - x1; y4 = segment[j + 5] - y1; y3 = segment[j + 3] - y1; y2 = segment[j + 1] - y1; xd = xd1 = yd = yd1 = 0; if (_abs(x4) < .01 && _abs(y4) < .01 && _abs(x2) + _abs(y2) < .01) { if (segment.length > 8) { segment.splice(j, 6); j -= 6; endIndex -= 6; } } else { for (i = 1; i <= resolution; i++) { t = inc * i; inv = 1 - t; xd = xd1 - (xd1 = (t * t * x4 + 3 * inv * (t * x3 + inv * x2)) * t); yd = yd1 - (yd1 = (t * t * y4 + 3 * inv * (t * y3 + inv * y2)) * t); l = _sqrt(yd * yd + xd * xd); if (l < min) { min = l; } length += l; samples[samplesIndex++] = length; } } x1 += x4; y1 += y4; } if (prevLength) { prevLength -= length; for (; samplesIndex < samples.length; samplesIndex++) { samples[samplesIndex] += prevLength; } } if (samples.length && min) { segment.totalLength = segLength = samples[samples.length - 1] || 0; segment.minLength = min; if (segLength / min < 9999) { l = lengthIndex = 0; for (i = 0; i < segLength; i += min) { lookup[l++] = samples[lengthIndex] < i ? ++lengthIndex : lengthIndex; } } } else { segment.totalLength = samples[0] = 0; } return startIndex ? length - samples[startIndex / 2 - 1] : length; } function cacheRawPathMeasurements(rawPath, resolution) { var pathLength, points, i; for (i = pathLength = points = 0; i < rawPath.length; i++) { rawPath[i].resolution = ~~resolution || 12; pathLength += measureSegment(rawPath[i]); points += rawPath[i].length; } rawPath.totalPoints = points; rawPath.totalLength = pathLength; return rawPath; } function arcToSegment(lastX, lastY, rx, ry, angle, largeArcFlag, sweepFlag, x, y) { if (lastX === x && lastY === y) { return; } rx = _abs(rx); ry = _abs(ry); var angleRad = angle % 360 * _DEG2RAD, cosAngle = _cos(angleRad), sinAngle = _sin(angleRad), PI = Math.PI, TWOPI = PI * 2, dx2 = (lastX - x) / 2, dy2 = (lastY - y) / 2, x1 = cosAngle * dx2 + sinAngle * dy2, y1 = -sinAngle * dx2 + cosAngle * dy2, x1_sq = x1 * x1, y1_sq = y1 * y1, radiiCheck = x1_sq / (rx * rx) + y1_sq / (ry * ry); if (radiiCheck > 1) { rx = _sqrt(radiiCheck) * rx; ry = _sqrt(radiiCheck) * ry; } var rx_sq = rx * rx, ry_sq = ry * ry, sq = (rx_sq * ry_sq - rx_sq * y1_sq - ry_sq * x1_sq) / (rx_sq * y1_sq + ry_sq * x1_sq); if (sq < 0) { sq = 0; } var coef = (largeArcFlag === sweepFlag ? -1 : 1) * _sqrt(sq), cx1 = coef * (rx * y1 / ry), cy1 = coef * -(ry * x1 / rx), sx2 = (lastX + x) / 2, sy2 = (lastY + y) / 2, cx = sx2 + (cosAngle * cx1 - sinAngle * cy1), cy = sy2 + (sinAngle * cx1 + cosAngle * cy1), ux = (x1 - cx1) / rx, uy = (y1 - cy1) / ry, vx = (-x1 - cx1) / rx, vy = (-y1 - cy1) / ry, temp = ux * ux + uy * uy, angleStart = (uy < 0 ? -1 : 1) * Math.acos(ux / _sqrt(temp)), angleExtent = (ux * vy - uy * vx < 0 ? -1 : 1) * Math.acos((ux * vx + uy * vy) / _sqrt(temp * (vx * vx + vy * vy))); isNaN(angleExtent) && (angleExtent = PI); if (!sweepFlag && angleExtent > 0) { angleExtent -= TWOPI; } else if (sweepFlag && angleExtent < 0) { angleExtent += TWOPI; } angleStart %= TWOPI; angleExtent %= TWOPI; var segments = Math.ceil(_abs(angleExtent) / (TWOPI / 4)), rawPath = [], angleIncrement = angleExtent / segments, controlLength = 4 / 3 * _sin(angleIncrement / 2) / (1 + _cos(angleIncrement / 2)), ma = cosAngle * rx, mb = sinAngle * rx, mc = sinAngle * -ry, md = cosAngle * ry, i; for (i = 0; i < segments; i++) { angle = angleStart + i * angleIncrement; x1 = _cos(angle); y1 = _sin(angle); ux = _cos(angle += angleIncrement); uy = _sin(angle); rawPath.push(x1 - controlLength * y1, y1 + controlLength * x1, ux + controlLength * uy, uy - controlLength * ux, ux, uy); } for (i = 0; i < rawPath.length; i += 2) { x1 = rawPath[i]; y1 = rawPath[i + 1]; rawPath[i] = x1 * ma + y1 * mc + cx; rawPath[i + 1] = x1 * mb + y1 * md + cy; } rawPath[i - 2] = x; rawPath[i - 1] = y; return rawPath; } function stringToRawPath(d) { var a = (d + "").replace(_scientific, function (m) { var n = +m; return n < 0.0001 && n > -0.0001 ? 0 : n; }).match(_svgPathExp) || [], path = [], relativeX = 0, relativeY = 0, twoThirds = 2 / 3, elements = a.length, points = 0, errorMessage = "ERROR: malformed path: " + d, i, j, x, y, command, isRelative, segment, startX, startY, difX, difY, beziers, prevCommand, flag1, flag2, line = function line(sx, sy, ex, ey) { difX = (ex - sx) / 3; difY = (ey - sy) / 3; segment.push(sx + difX, sy + difY, ex - difX, ey - difY, ex, ey); }; if (!d || !isNaN(a[0]) || isNaN(a[1])) { console.log(errorMessage); return path; } for (i = 0; i < elements; i++) { prevCommand = command; if (isNaN(a[i])) { command = a[i].toUpperCase(); isRelative = command !== a[i]; } else { i--; } x = +a[i + 1]; y = +a[i + 2]; if (isRelative) { x += relativeX; y += relativeY; } if (!i) { startX = x; startY = y; } if (command === "M") { if (segment) { if (segment.length < 8) { path.length -= 1; } else { points += segment.length; } _segmentIsClosed(segment); } relativeX = startX = x; relativeY = startY = y; segment = [x, y]; path.push(segment); i += 2; command = "L"; } else if (command === "C") { if (!segment) { segment = [0, 0]; } if (!isRelative) { relativeX = relativeY = 0; } segment.push(x, y, relativeX + a[i + 3] * 1, relativeY + a[i + 4] * 1, relativeX += a[i + 5] * 1, relativeY += a[i + 6] * 1); i += 6; } else if (command === "S") { difX = relativeX; difY = relativeY; if (prevCommand === "C" || prevCommand === "S") { difX += relativeX - segment[segment.length - 4]; difY += relativeY - segment[segment.length - 3]; } if (!isRelative) { relativeX = relativeY = 0; } segment.push(difX, difY, x, y, relativeX += a[i + 3] * 1, relativeY += a[i + 4] * 1); i += 4; } else if (command === "Q") { difX = relativeX + (x - relativeX) * twoThirds; difY = relativeY + (y - relativeY) * twoThirds; if (!isRelative) { relativeX = relativeY = 0; } relativeX += a[i + 3] * 1; relativeY += a[i + 4] * 1; segment.push(difX, difY, relativeX + (x - relativeX) * twoThirds, relativeY + (y - relativeY) * twoThirds, relativeX, relativeY); i += 4; } else if (command === "T") { difX = relativeX - segment[segment.length - 4]; difY = relativeY - segment[segment.length - 3]; segment.push(relativeX + difX, relativeY + difY, x + (relativeX + difX * 1.5 - x) * twoThirds, y + (relativeY + difY * 1.5 - y) * twoThirds, relativeX = x, relativeY = y); i += 2; } else if (command === "H") { line(relativeX, relativeY, relativeX = x, relativeY); i += 1; } else if (command === "V") { line(relativeX, relativeY, relativeX, relativeY = x + (isRelative ? relativeY - relativeX : 0)); i += 1; } else if (command === "L" || command === "Z") { if (command === "Z") { x = startX; y = startY; segment.closed = true; } if (command === "L" || _abs(relativeX - x) > 0.5 || _abs(relativeY - y) > 0.5) { line(relativeX, relativeY, x, y); if (command === "L") { i += 2; } } relativeX = x; relativeY = y; } else if (command === "A") { flag1 = a[i + 4]; flag2 = a[i + 5]; difX = a[i + 6]; difY = a[i + 7]; j = 7; if (flag1.length > 1) { if (flag1.length < 3) { difY = difX; difX = flag2; j--; } else { difY = flag2; difX = flag1.substr(2); j -= 2; } flag2 = flag1.charAt(1); flag1 = flag1.charAt(0); } beziers = arcToSegment(relativeX, relativeY, +a[i + 1], +a[i + 2], +a[i + 3], +flag1, +flag2, (isRelative ? relativeX : 0) + difX * 1, (isRelative ? relativeY : 0) + difY * 1); i += j; if (beziers) { for (j = 0; j < beziers.length; j++) { segment.push(beziers[j]); } } relativeX = segment[segment.length - 2]; relativeY = segment[segment.length - 1]; } else { console.log(errorMessage); } } i = segment.length; if (i < 6) { path.pop(); i = 0; } else { _segmentIsClosed(segment); } path.totalPoints = points + i; return path; } function segmentToDistributedPoints(segment, totalPoints) { segment.samples || measureSegment(segment); var samples = segment.samples, lookup = segment.lookup, resolution = segment.resolution, totalLength = segment.totalLength, points = segment.slice(0, 2), curveStoppingPoints = [], l = segment.length - 4, i = 6, limit = 0.2, startLength = 0, curvePointsCumulative = 0, t, curvePoints, min, max, ci, ratioInc, j, inv, curveLength, length, a, nonSmooth, curveStoppingPointIndex, sampleIndex; for (; i < l; i += 6) { if (Math.abs(_atan2(segment[i + 1] - segment[i - 1], segment[i] - segment[i - 2]) - _atan2(segment[i + 3] - segment[i + 1], segment[i + 2] - segment[i])) > limit) { curveStoppingPoints.push(i); } } curveStoppingPoints.push(segment.length - 2); l = curveStoppingPoints.length; points.nonSmooth = nonSmooth = [1]; if (totalPoints > l) { totalPoints -= l; for (ci = 0; ci < l; ci++) { curveStoppingPointIndex = curveStoppingPoints[ci]; sampleIndex = Math.round(curveStoppingPointIndex / 6 * resolution); curveLength = samples[sampleIndex - 1] - startLength; curvePoints = Math.round(samples[sampleIndex - 1] / totalLength * totalPoints) - curvePointsCumulative; curvePointsCumulative += curvePoints; ratioInc = 1 / (curvePoints + 1); for (j = 1; j <= curvePoints; j++) { length = startLength + curveLength * j * ratioInc; i = lookup.length ? lookup[length < totalLength ? ~~(length / segment.minLength) : lookup.length - 1] || 0 : _getSampleIndex(samples, length, length / totalLength); min = i ? samples[i - 1] : 0; max = samples[i]; if (max < length) { min = max; max = samples[++i]; } t = 1 / resolution * ((length - min) / (max - min) + i % resolution) || 0; inv = 1 - t; i = ~~(i / resolution) * 6; a = segment[i]; points.push(_round((t * t * (segment[i + 6] - a) + 3 * inv * (t * (segment[i + 4] - a) + inv * (segment[i + 2] - a))) * t + a), _round((t * t * (segment[i + 7] - (a = segment[i + 1])) + 3 * inv * (t * (segment[i + 5] - a) + inv * (segment[i + 3] - a))) * t + a)); } nonSmooth[points.length] = 1; points.push(segment[curveStoppingPointIndex], segment[curveStoppingPointIndex + 1]); startLength += curveLength; } } i = segment.length - 2; if (segment.closed && Math.abs(_atan2(segment[i + 1] - segment[i - 1], segment[i] - segment[i - 2]) - _atan2(segment[3] - segment[1], segment[2] - segment[0])) <= limit) { nonSmooth[0] = nonSmooth[nonSmooth.length - 1] = 0; } return points; } function pointsToSegment(points, curviness) { _abs(points[0] - points[2]) < 1e-4 && _abs(points[1] - points[3]) < 1e-4 && (points = points.slice(2)); var l = points.length - 2, x = +points[0], y = +points[1], nextX = +points[2], nextY = +points[3], segment = [x, y, x, y], dx2 = nextX - x, dy2 = nextY - y, nonSmooth = points.nonSmooth || [], closed = Math.abs(points[l] - x) < 0.001 && Math.abs(points[l + 1] - y) < 0.001, prevX, prevY, i, dx1, dy1, r1, r2, r3, tl, mx1, mx2, mxm, my1, my2, mym; if (!l) { return [x, y, x, y, x, y, x, y]; } if (closed) { points.push(nextX, nextY); nextX = x; nextY = y; x = points[l - 2]; y = points[l - 1]; points.unshift(x, y); l += 4; nonSmooth = [0, 0].concat(nonSmooth); } curviness = curviness || curviness === 0 ? +curviness : 1; for (i = 2; i < l; i += 2) { prevX = x; prevY = y; x = nextX; y = nextY; nextX = +points[i + 2]; nextY = +points[i + 3]; if (x === nextX && y === nextY) { continue; } dx1 = dx2; dy1 = dy2; dx2 = nextX - x; dy2 = nextY - y; if (nonSmooth[i]) { segment.push(x - (x - prevX) / 4, y - (y - prevY) / 4, x, y, x + (nextX - x) / 4, y + (nextY - y) / 4); continue; } r1 = _sqrt(dx1 * dx1 + dy1 * dy1); r2 = _sqrt(dx2 * dx2 + dy2 * dy2); r3 = _sqrt(Math.pow(dx2 / r2 + dx1 / r1, 2) + Math.pow(dy2 / r2 + dy1 / r1, 2)); tl = (r1 + r2) * curviness * 0.25 / r3; mx1 = x - (x - prevX) * (r1 ? tl / r1 : 0); mx2 = x + (nextX - x) * (r2 ? tl / r2 : 0); mxm = x - (mx1 + ((mx2 - mx1) * (r1 * 3 / (r1 + r2) + 0.5) / 4 || 0)); my1 = y - (y - prevY) * (r1 ? tl / r1 : 0); my2 = y + (nextY - y) * (r2 ? tl / r2 : 0); mym = y - (my1 + ((my2 - my1) * (r1 * 3 / (r1 + r2) + 0.5) / 4 || 0)); segment.push(_round(mx1 + mxm), _round(my1 + mym), _round(x), _round(y), _round(mx2 + mxm), _round(my2 + mym)); } x !== nextX || y !== nextY || segment.length < 4 ? segment.push(_round(nextX), _round(nextY), _round(nextX), _round(nextY)) : segment.length -= 2; if (segment.length === 2) { segment.push(x, y, x, y, x, y); } else if (closed) { segment.splice(0, 6); segment.length -= 6; } segment.closed = closed; return segment; } function rawPathToString(rawPath) { if (_isNumber(rawPath[0])) { rawPath = [rawPath]; } var result = "", l = rawPath.length, sl, s, i, segment; for (s = 0; s < l; s++) { segment = rawPath[s]; result += "M" + _round(segment[0]) + "," + _round(segment[1]) + " C"; sl = segment.length; for (i = 2; i < sl; i++) { result += _round(segment[i++]) + "," + _round(segment[i++]) + " " + _round(segment[i++]) + "," + _round(segment[i++]) + " " + _round(segment[i++]) + "," + _round(segment[i]) + " "; } if (segment.closed) { result += "z"; } } return result; } var gsap, _toArray, _lastLinkedAnchor, _coreInitted, PluginClass, _reverting, _getGSAP = function _getGSAP() { return gsap || typeof window !== "undefined" && (gsap = window.gsap) && gsap.registerPlugin && gsap; }, _isFunction = function _isFunction(value) { return typeof value === "function"; }, _atan2$1 = Math.atan2, _cos$1 = Math.cos, _sin$1 = Math.sin, _sqrt$1 = Math.sqrt, _PI = Math.PI, _2PI = _PI * 2, _angleMin = _PI * 0.3, _angleMax = _PI * 0.7, _bigNum = 1e20, _numExp = /[-+=.]*\d+[.e\-+]*\d*[e\-+]*\d*/gi, _selectorExp$1 = /(^[#.][a-z]|[a-y][a-z])/i, _commands = /[achlmqstvz]/i, _log = function _log(message) { return console && console.warn(message); }, _round$1 = function _round(value) { return Math.round(value * 1e5) / 1e5 || 0; }, _getAverageXY = function _getAverageXY(segment) { var l = segment.length, x = 0, y = 0, i; for (i = 0; i < l; i++) { x += segment[i++]; y += segment[i]; } return [x / (l / 2), y / (l / 2)]; }, _getSize = function _getSize(segment) { var l = segment.length, xMax = segment[0], xMin = xMax, yMax = segment[1], yMin = yMax, x, y, i; for (i = 6; i < l; i += 6) { x = segment[i]; y = segment[i + 1]; if (x > xMax) { xMax = x; } else if (x < xMin) { xMin = x; } if (y > yMax) { yMax = y; } else if (y < yMin) { yMin = y; } } segment.centerX = (xMax + xMin) / 2; segment.centerY = (yMax + yMin) / 2; return segment.size = (xMax - xMin) * (yMax - yMin); }, _getTotalSize = function _getTotalSize(rawPath, samplesPerBezier) { if (samplesPerBezier === void 0) { samplesPerBezier = 3; } var j = rawPath.length, xMax = rawPath[0][0], xMin = xMax, yMax = rawPath[0][1], yMin = yMax, inc = 1 / samplesPerBezier, l, x, y, i, segment, k, t, inv, x1, y1, x2, x3, x4, y2, y3, y4; while (--j > -1) { segment = rawPath[j]; l = segment.length; for (i = 6; i < l; i += 6) { x1 = segment[i]; y1 = segment[i + 1]; x2 = segment[i + 2] - x1; y2 = segment[i + 3] - y1; x3 = segment[i + 4] - x1; y3 = segment[i + 5] - y1; x4 = segment[i + 6] - x1; y4 = segment[i + 7] - y1; k = samplesPerBezier; while (--k > -1) { t = inc * k; inv = 1 - t; x = (t * t * x4 + 3 * inv * (t * x3 + inv * x2)) * t + x1; y = (t * t * y4 + 3 * inv * (t * y3 + inv * y2)) * t + y1; if (x > xMax) { xMax = x; } else if (x < xMin) { xMin = x; } if (y > yMax) { yMax = y; } else if (y < yMin) { yMin = y; } } } } rawPath.centerX = (xMax + xMin) / 2; rawPath.centerY = (yMax + yMin) / 2; rawPath.left = xMin; rawPath.width = xMax - xMin; rawPath.top = yMin; rawPath.height = yMax - yMin; return rawPath.size = (xMax - xMin) * (yMax - yMin); }, _sortByComplexity = function _sortByComplexity(a, b) { return b.length - a.length; }, _sortBySize = function _sortBySize(a, b) { var sizeA = a.size || _getSize(a), sizeB = b.size || _getSize(b); return Math.abs(sizeB - sizeA) < (sizeA + sizeB) / 20 ? b.centerX - a.centerX || b.centerY - a.centerY : sizeB - sizeA; }, _offsetSegment = function _offsetSegment(segment, shapeIndex) { var a = segment.slice(0), l = segment.length, wrap = l - 2, i, index; shapeIndex = shapeIndex | 0; for (i = 0; i < l; i++) { index = (i + shapeIndex) % wrap; segment[i++] = a[index]; segment[i] = a[index + 1]; } }, _getTotalMovement = function _getTotalMovement(sb, eb, shapeIndex, offsetX, offsetY) { var l = sb.length, d = 0, wrap = l - 2, index, i, x, y; shapeIndex *= 6; for (i = 0; i < l; i += 6) { index = (i + shapeIndex) % wrap; y = sb[index] - (eb[i] - offsetX); x = sb[index + 1] - (eb[i + 1] - offsetY); d += _sqrt$1(x * x + y * y); } return d; }, _getClosestShapeIndex = function _getClosestShapeIndex(sb, eb, checkReverse) { var l = sb.length, sCenter = _getAverageXY(sb), eCenter = _getAverageXY(eb), offsetX = eCenter[0] - sCenter[0], offsetY = eCenter[1] - sCenter[1], min = _getTotalMovement(sb, eb, 0, offsetX, offsetY), minIndex = 0, copy, d, i; for (i = 6; i < l; i += 6) { d = _getTotalMovement(sb, eb, i / 6, offsetX, offsetY); if (d < min) { min = d; minIndex = i; } } if (checkReverse) { copy = sb.slice(0); reverseSegment(copy); for (i = 6; i < l; i += 6) { d = _getTotalMovement(copy, eb, i / 6, offsetX, offsetY); if (d < min) { min = d; minIndex = -i; } } } return minIndex / 6; }, _getClosestAnchor = function _getClosestAnchor(rawPath, x, y) { var j = rawPath.length, closestDistance = _bigNum, closestX = 0, closestY = 0, segment, dx, dy, d, i, l; while (--j > -1) { segment = rawPath[j]; l = segment.length; for (i = 0; i < l; i += 6) { dx = segment[i] - x; dy = segment[i + 1] - y; d = _sqrt$1(dx * dx + dy * dy); if (d < closestDistance) { closestDistance = d; closestX = segment[i]; closestY = segment[i + 1]; } } } return [closestX, closestY]; }, _getClosestSegment = function _getClosestSegment(bezier, pool, startIndex, sortRatio, offsetX, offsetY) { var l = pool.length, index = 0, minSize = Math.min(bezier.size || _getSize(bezier), pool[startIndex].size || _getSize(pool[startIndex])) * sortRatio, min = _bigNum, cx = bezier.centerX + offsetX, cy = bezier.centerY + offsetY, size, i, dx, dy, d; for (i = startIndex; i < l; i++) { size = pool[i].size || _getSize(pool[i]); if (size < minSize) { break; } dx = pool[i].centerX - cx; dy = pool[i].centerY - cy; d = _sqrt$1(dx * dx + dy * dy); if (d < min) { index = i; min = d; } } d = pool[index]; pool.splice(index, 1); return d; }, _addAnchorsToBezier = function _addAnchorsToBezier(segment, i, quantity) { if (quantity === void 0) { quantity = 1; } var ax = segment[i], ay = segment[i + 1], cp1x = segment[i + 2], cp1y = segment[i + 3], cp2x = segment[i + 4], cp2y = segment[i + 5], bx = segment[i + 6], by = segment[i + 7], t, x1a, x2, y1a, y2, x1, y1, x2a, y2a; while (quantity-- > 0) { t = 1 - 1 / (quantity + 2); x1a = ax + (cp1x - ax) * t; x2 = cp1x + (cp2x - cp1x) * t; y1a = ay + (cp1y - ay) * t; y2 = cp1y + (cp2y - cp1y) * t; x1 = x1a + (x2 - x1a) * t; y1 = y1a + (y2 - y1a) * t; x2a = cp2x + (bx - cp2x) * t; y2a = cp2y + (by - cp2y) * t; x2 += (x2a - x2) * t; y2 += (y2a - y2) * t; segment.splice(i + 2, 4, cp1x = _round$1(x1a), cp1y = _round$1(y1a), cp2x = _round$1(x1), cp2y = _round$1(y1), bx = _round$1(x1 + (x2 - x1) * t), by = _round$1(y1 + (y2 - y1) * t), _round$1(x2), _round$1(y2), _round$1(x2a), _round$1(y2a)); } }, _getLargestIndex = function _getLargestIndex(a) { var i = a.length, max = -_bigNum, largestIndex; while (i--) { if (a[i] > max) { max = a[i]; largestIndex = i; } } return largestIndex; }, _subdivideSegmentQty = function _subdivideSegmentQty(segment, quantity) { var distances = [], anchorsToAdd = [], l = segment.length - 2, i = 0; for (; i < l; i += 6) { distances.push(Math.pow(segment[i] - segment[i + 6], 2) + Math.pow(segment[i + 1] - segment[i + 7], 2)); } while (quantity--) { i = _getLargestIndex(distances); anchorsToAdd[i] = l = (anchorsToAdd[i] || 0) + 1; distances[i] *= l / (l + 1); } i = distances.length; while (i--) { anchorsToAdd[i] && _addAnchorsToBezier(segment, i * 6, anchorsToAdd[i]); } }, _getDefaultSmoothPoints = function _getDefaultSmoothPoints(rawPath, skipMeasure) { skipMeasure || cacheRawPathMeasurements(rawPath); return Math.max(4, Math.round(rawPath.totalLength / 4)); }, _cloneAndSortRawPath = function _cloneAndSortRawPath(ar) { return ar.slice(0).sort(_sortByComplexity); }, _segmentCanBeIgnored = function _segmentCanBeIgnored(segment) { var x = segment[0], y = segment[1], i = 2; for (; i < segment.length; i += 2) { if (Math.abs(segment[i] - x) > 0.01 || Math.abs(segment[i + 1] - y) > 0.01) { return false; } } return true; }, _smoothRawPath = function _smoothRawPath(rawPath, config) { config = config || {}; var _config = config, redraw = _config.redraw, points = _config.points, _config$maxSegments = _config.maxSegments, maxSegments = _config$maxSegments === void 0 ? 999 : _config$maxSegments, pointsAdded = 0, sortedRawPath = rawPath, templateRawPath = Array.isArray(points) ? points : 0, segmentPointsToAdd, j, segment, smoothSegment, anchorDistance; redraw = redraw !== false; if (redraw) { cacheRawPathMeasurements(rawPath); } else { rawPath.totalPoints = 0; j = rawPath.length; while (j--) { rawPath.totalPoints += rawPath[j].length; } } if (templateRawPath) { sortedRawPath = _cloneAndSortRawPath(rawPath); templateRawPath = _cloneAndSortRawPath(templateRawPath); anchorDistance = templateRawPath[0].totalLength / Math.round(templateRawPath[0].length / 6); } else { if (!points || points === "auto") { points = _getDefaultSmoothPoints(rawPath, redraw); redraw || (points -= Math.round(rawPath.totalPoints / 6)); } points = Math.max(redraw ? 10 : 4, Math.min(999, points)); } for (j = 0; j < sortedRawPath.length; j++) { segment = sortedRawPath[j]; segmentPointsToAdd = Math.max(redraw ? 10 : 4, templateRawPath ? Math.round(templateRawPath[j] ? templateRawPath[j].length / 6 : sortedRawPath[j].totalLength / anchorDistance || 0) : Math.round((pointsAdded / points + (redraw ? segment.totalLength / rawPath.totalLength : segment.length / rawPath.totalPoints)) * points) - pointsAdded); if (j >= maxSegments || templateRawPath && (!templateRawPath[j] || _segmentCanBeIgnored(templateRawPath[j]))) ; else if (redraw) { var _segment; smoothSegment = pointsToSegment(segmentToDistributedPoints(segment, segmentPointsToAdd), config.curviness); segment.length = 0; (_segment = segment).push.apply(_segment, smoothSegment); } else { _subdivideSegmentQty(segment, segmentPointsToAdd); } pointsAdded += segmentPointsToAdd; } return rawPath; }, _equalizeSegmentQuantity = function _equalizeSegmentQuantity(start, end, shapeIndex, map, fillSafe) { var dif = end.length - start.length, longer = dif > 0 ? end : start, shorter = dif > 0 ? start : end, added = 0, sortMethod = map === "complexity" ? _sortByComplexity : _sortBySize, sortRatio = map === "position" ? 0 : typeof map === "number" ? map : 0.8, i = shorter.length, shapeIndices = typeof shapeIndex === "object" && shapeIndex.push ? shapeIndex.slice(0) : [shapeIndex], reverse = shapeIndices[0] === "reverse" || shapeIndices[0] < 0, log = shapeIndex === "log", eb, sb, b, x, y, offsetX, offsetY; if (!shorter[0]) { return; } if (longer.length > 1) { start.sort(sortMethod); end.sort(sortMethod); longer.size || _getTotalSize(longer); shorter.size || _getTotalSize(shorter); offsetX = longer.centerX - shorter.centerX; offsetY = longer.centerY - shorter.centerY; if (sortMethod === _sortBySize) { for (i = 0; i < shorter.length; i++) { longer.splice(i, 0, _getClosestSegment(shorter[i], longer, i, sortRatio, offsetX, offsetY)); } } } if (dif) { dif < 0 && (dif = -dif); longer[0].length > shorter[0].length && _subdivideSegmentQty(shorter[0], (longer[0].length - shorter[0].length) / 6 | 0); i = shorter.length; while (added < dif) { x = longer[i].size || _getSize(longer[i]); b = _getClosestAnchor(shorter, longer[i].centerX, longer[i].centerY); x = b[0]; y = b[1]; shorter[i++] = [x, y, x, y, x, y, x, y]; shorter.totalPoints += 8; added++; } } for (i = 0; i < start.length; i++) { eb = end[i]; sb = start[i]; dif = eb.length - sb.length; if (dif < 0) { _subdivideSegmentQty(eb, -dif / 6 | 0); } else if (dif > 0) { _subdivideSegmentQty(sb, dif / 6 | 0); } if (reverse && fillSafe !== false && !sb.reversed) { reverseSegment(sb); } shapeIndex = shapeIndices[i] || shapeIndices[i] === 0 ? shapeIndices[i] : "auto"; if (shapeIndex) { if (sb.closed || Math.abs(sb[0] - sb[sb.length - 2]) < 0.5 && Math.abs(sb[1] - sb[sb.length - 1]) < 0.5) { if (shapeIndex === "auto" || shapeIndex === "log") { shapeIndices[i] = shapeIndex = _getClosestShapeIndex(sb, eb, !i || fillSafe === false); if (shapeIndex < 0) { reverse = true; reverseSegment(sb); shapeIndex = -shapeIndex; } _offsetSegment(sb, shapeIndex * 6); } else if (shapeIndex !== "reverse") { if (i && shapeIndex < 0) { reverseSegment(sb); } _offsetSegment(sb, (shapeIndex < 0 ? -shapeIndex : shapeIndex) * 6); } } else if (!reverse && (shapeIndex === "auto" && Math.abs(eb[0] - sb[0]) + Math.abs(eb[1] - sb[1]) + Math.abs(eb[eb.length - 2] - sb[sb.length - 2]) + Math.abs(eb[eb.length - 1] - sb[sb.length - 1]) > Math.abs(eb[0] - sb[sb.length - 2]) + Math.abs(eb[1] - sb[sb.length - 1]) + Math.abs(eb[eb.length - 2] - sb[0]) + Math.abs(eb[eb.length - 1] - sb[1]) || shapeIndex % 2)) { reverseSegment(sb); shapeIndices[i] = -1; reverse = true; } else if (shapeIndex === "auto") { shapeIndices[i] = 0; } else if (shapeIndex === "reverse") { shapeIndices[i] = -1; } if (sb.closed !== eb.closed) { sb.closed = eb.closed = false; } } } log && _log("shapeIndex:[" + shapeIndices.join(",") + "]"); start.shapeIndex = shapeIndices; return shapeIndices; }, _pathFilter = function _pathFilter(a, shapeIndex, map, precompile, fillSafe) { var start = stringToRawPath(a[0]), end = stringToRawPath(a[1]); if (!_equalizeSegmentQuantity(start, end, shapeIndex || shapeIndex === 0 ? shapeIndex : "auto", map, fillSafe)) { return; } a[0] = rawPathToString(start); a[1] = rawPathToString(end); (precompile === "log" || precompile === true) && _log('precompile:["' + a[0] + '","' + a[1] + '"]'); }, _offsetPoints = function _offsetPoints(text, offset) { if (!offset) { return text; } var a = text.match(_numExp) || [], l = a.length, s = "", inc, i, j; if (offset === "reverse") { i = l - 1; inc = -2; } else { i = ((parseInt(offset, 10) || 0) * 2 + 1 + l * 100) % l; inc = 2; } for (j = 0; j < l; j += 2) { s += a[i - 1] + "," + a[i] + " "; i = (i + inc) % l; } return s; }, _equalizePointQuantity = function _equalizePointQuantity(a, quantity) { var tally = 0, x = parseFloat(a[0]), y = parseFloat(a[1]), s = x + "," + y + " ", max = 0.999999, newPointsPerSegment, i, l, j, factor, nextX, nextY; l = a.length; newPointsPerSegment = quantity * 0.5 / (l * 0.5 - 1); for (i = 0; i < l - 2; i += 2) { tally += newPointsPerSegment; nextX = parseFloat(a[i + 2]); nextY = parseFloat(a[i + 3]); if (tally > max) { factor = 1 / (Math.floor(tally) + 1); j = 1; while (tally > max) { s += (x + (nextX - x) * factor * j).toFixed(2) + "," + (y + (nextY - y) * factor * j).toFixed(2) + " "; tally--; j++; } } s += nextX + "," + nextY + " "; x = nextX; y = nextY; } return s; }, _pointsFilter = function _pointsFilter(a) { var startNums = a[0].match(_numExp) || [], endNums = a[1].match(_numExp) || [], dif = endNums.length - startNums.length; if (dif > 0) { a[0] = _equalizePointQuantity(startNums, dif); } else { a[1] = _equalizePointQuantity(endNums, -dif); } }, _buildPointsFilter = function _buildPointsFilter(shapeIndex) { return !isNaN(shapeIndex) ? function (a) { _pointsFilter(a); a[1] = _offsetPoints(a[1], parseInt(shapeIndex, 10)); } : _pointsFilter; }, _parseShape = function _parseShape(shape, forcePath, target) { var isString = typeof shape === "string", e, type; if (!isString || _selectorExp$1.test(shape) || (shape.match(_numExp) || []).length < 3) { e = _toArray(shape)[0]; if (e) { type = (e.nodeName + "").toUpperCase(); if (forcePath && type !== "PATH") { e = convertToPath(e, false); type = "PATH"; } shape = e.getAttribute(type === "PATH" ? "d" : "points") || ""; if (e === target) { shape = e.getAttributeNS(null, "data-original") || shape; } } else { _log("WARNING: invalid morph to: " + shape); shape = false; } } return shape; }, _recordControlPointData = function _recordControlPointData(rawPath) { var j = rawPath.length, segment, x, y, x2, y2, i, l, cpData; while (--j > -1) { segment = rawPath[j]; cpData = segment.cpData = segment.cpData || []; cpData.length = 0; l = segment.length - 2; for (i = 0; i < l; i += 6) { x = segment[i] - segment[i + 2]; y = segment[i + 1] - segment[i + 3]; x2 = segment[i + 6] - segment[i + 4]; y2 = segment[i + 7] - segment[i + 5]; cpData[i + 2] = _atan2$1(y, x); cpData[i + 3] = _sqrt$1(x * x + y * y); cpData[i + 4] = _atan2$1(y2, x2); cpData[i + 5] = _sqrt$1(x2 * x2 + y2 * y2); } } return rawPath; }, _parseOriginFactors = function _parseOriginFactors(v) { var a = v.trim().split(" "), x = ~v.indexOf("left") ? 0 : ~v.indexOf("right") ? 100 : isNaN(parseFloat(a[0])) ? 50 : parseFloat(a[0]), y = ~v.indexOf("top") ? 0 : ~v.indexOf("bottom") ? 100 : isNaN(parseFloat(a[1])) ? 50 : parseFloat(a[1]); return { x: x / 100, y: y / 100 }; }, _shortAngle = function _shortAngle(dif) { return dif !== dif % _PI ? dif + (dif < 0 ? _2PI : -_2PI) : dif; }, _morphMessage = "Use MorphSVGPlugin.convertToPath() to convert to a path before morphing.", _tweenRotation = function _tweenRotation(start, end, i, linkedPT) { var so = this._origin, eo = this._eOrigin, dx = start[i] - so.x, dy = start[i + 1] - so.y, d = _sqrt$1(dx * dx + dy * dy), sa = _atan2$1(dy, dx), angleDif, _short; dx = end[i] - eo.x; dy = end[i + 1] - eo.y; angleDif = _atan2$1(dy, dx) - sa; _short = _shortAngle(angleDif); if (!linkedPT && _lastLinkedAnchor && Math.abs(_short + _lastLinkedAnchor.ca) < _angleMin) { linkedPT = _lastLinkedAnchor; } return this._anchorPT = _lastLinkedAnchor = { _next: this._anchorPT, t: start, sa: sa, ca: linkedPT && _short * linkedPT.ca < 0 && Math.abs(_short) > _angleMax ? angleDif : _short, sl: d, cl: _sqrt$1(dx * dx + dy * dy) - d, i: i }; }, _initCore = function _initCore(required) { gsap = _getGSAP(); PluginClass = PluginClass || gsap && gsap.plugins.morphSVG; if (gsap && PluginClass) { _toArray = gsap.utils.toArray; _reverting = gsap.core.reverting || function () {}; PluginClass.prototype._tweenRotation = _tweenRotation; _coreInitted = 1; } else if (required) { _log("Please gsap.registerPlugin(MorphSVGPlugin)"); } }; var MorphSVGPlugin = { version: "3.14.2", name: "morphSVG", rawVars: 1, register: function register(core, Plugin) { gsap = core; PluginClass = Plugin; _initCore(); }, init: function init(target, value, tween, index, targets) { _coreInitted || _initCore(1); if (!value) { _log("invalid shape"); return false; } _isFunction(value) && (value = value.call(tween, index, target, targets)); var type, p, pt, shape, isPoly, shapeIndex, map, startCPData, endCPData, start, end, i, j, l, startSeg, endSeg, precompiled, originFactors, useRotation, curveMode; if (typeof value === "string" || value.getBBox || value[0]) { value = { shape: value }; } else if (typeof value === "object") { type = {}; for (p in value) { type[p] = _isFunction(value[p]) && p !== "render" ? value[p].call(tween, index, target, targets) : value[p]; } value = type; } var cs = target.nodeType ? window.getComputedStyle(target) : {}, fill = cs.fill + "", fillSafe = !(fill === "none" || (fill.match(_numExp) || [])[3] === "0" || cs.fillRule === "evenodd"), smooth = value.smooth, origins = (value.origin || "50 50").split(","); smooth === true || smooth === "auto" ? smooth = {} : typeof smooth === "number" && (smooth = { points: smooth }); type = (target.nodeName + "").toUpperCase(); isPoly = type === "POLYLINE" || type === "POLYGON"; if (type !== "PATH" && !isPoly && !value.prop) { _log("Cannot morph a <" + type + "> element. " + _morphMessage); return false; } p = type === "PATH" ? "d" : "points"; if (!value.prop && !_isFunction(target.setAttribute)) { return false; } shape = _parseShape(value.shape || value.d || value.points || "", p === "d", target); if (isPoly && _commands.test(shape)) { _log("A <" + type + "> cannot accept path data. " + _morphMessage); return false; } shapeIndex = value.shapeIndex || value.shapeIndex === 0 ? value.shapeIndex : "auto"; map = value.map || MorphSVGPlugin.defaultMap; this._prop = value.prop; this._render = value.render || MorphSVGPlugin.defaultRender; this._apply = "updateTarget" in value ? value.updateTarget : MorphSVGPlugin.defaultUpdateTarget; this._rnd = Math.pow(10, isNaN(value.precision) ? 2 : +value.precision); this._tween = tween; if (shape) { this._target = target; precompiled = typeof value.precompile === "object"; start = this._original = this._prop ? target[this._prop] : target.getAttribute(p); if (!this._prop && !target.getAttributeNS(null, "data-original")) { target.setAttributeNS(null, "data-original", start); } if (p === "d" || this._prop) { start = stringToRawPath(precompiled ? value.precompile[0] : start); end = stringToRawPath(precompiled ? value.precompile[1] : shape); if (smooth) { j = start.length; while (--j) { _segmentCanBeIgnored(start[j]) && start.splice(j, 1); } _smoothRawPath(start, _extends({}, smooth, { points: +smooth.points || Math.max(_getDefaultSmoothPoints(start), _getDefaultSmoothPoints(end)), maxSegments: end.length })); _smoothRawPath(end, smooth.redraw === false ? smooth : _extends({}, smooth, { points: start })); } if (!precompiled && !_equalizeSegmentQuantity(start, end, shapeIndex, map, fillSafe)) { return false; } if (value.precompile === "log" || value.precompile === true) { _log('precompile:["' + rawPathToString(start) + '","' + rawPathToString(end) + '"]'); } useRotation = (value.type || MorphSVGPlugin.defaultType) !== "linear"; curveMode = value.curveMode || useRotation; _recordControlPointData(start); _recordControlPointData(end); if (useRotation) { start.size || _getTotalSize(start); end.size || _getTotalSize(end); originFactors = _parseOriginFactors(origins[0]); this._origin = start.origin = { x: start.left + originFactors.x * start.width, y: start.top + originFactors.y * start.height }; origins[1] && (originFactors = _parseOriginFactors(origins[1])); this._eOrigin = { x: end.left + originFactors.x * end.width, y: