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,787 lines (1,500 loc) • 90 kB
JavaScript
(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';
var _svgPathExp = /[achlmqstvz]|(-?\d*\.?\d*(?:e[\-+]?\d+)?)[0-9]/ig,
_scientific = /[\+\-]?\d*\.?\d+e[\+\-]?\d+/ig,
_DEG2RAD = Math.PI / 180,
_sin = Math.sin,
_cos = Math.cos,
_abs = Math.abs,
_sqrt = Math.sqrt,
_largeNum = 1e8,
_isNumber = function _isNumber(value) {
return typeof value === "number";
},
_roundingNum = 1e5,
_round = function _round(value) {
return Math.round(value * _roundingNum) / _roundingNum || 0;
},
_copyMetaData = function _copyMetaData(source, copy) {
copy.totalLength = source.totalLength;
if (source.samples) {
copy.samples = source.samples.slice(0);
copy.lookup = source.lookup.slice(0);
copy.minLength = source.minLength;
copy.resolution = source.resolution;
} else if (source.totalPoints) {
copy.totalPoints = source.totalPoints;
}
return copy;
},
_bestDistance;
function copyRawPath(rawPath) {
var a = [],
i = 0;
for (; i < rawPath.length; i++) {
a[i] = _copyMetaData(rawPath[i], rawPath[i].slice(0));
}
return _copyMetaData(rawPath, a);
}
function subdivideSegment(segment, i, t) {
if (t <= 0 || t >= 1) {
return 0;
}
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],
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, _round(x1a), _round(y1a), _round(x1), _round(y1), _round(x1 + (x2 - x1) * t), _round(y1 + (y2 - y1) * t), _round(x2), _round(y2), _round(x2a), _round(y2a));
segment.samples && segment.samples.splice(i / 6 * segment.resolution | 0, 0, 0, 0, 0, 0, 0, 0);
return 6;
}
function transformRawPath(rawPath, a, b, c, d, tx, ty) {
var j = rawPath.length,
segment,
l,
i,
x,
y;
while (--j > -1) {
segment = rawPath[j];
l = segment.length;
for (i = 0; i < l; i += 2) {
x = segment[i];
y = segment[i + 1];
segment[i] = x * a + y * c + tx;
segment[i + 1] = x * b + y * d + ty;
}
}
rawPath._dirty = 1;
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;
}
}
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 if (segment[0] === segment[i - 2] && segment[1] === segment[i - 1]) {
segment.closed = true;
}
path.totalPoints = points + i;
return path;
}
function bezierToPoints(x1, y1, x2, y2, x3, y3, x4, y4, threshold, points, index) {
var x12 = (x1 + x2) / 2,
y12 = (y1 + y2) / 2,
x23 = (x2 + x3) / 2,
y23 = (y2 + y3) / 2,
x34 = (x3 + x4) / 2,
y34 = (y3 + y4) / 2,
x123 = (x12 + x23) / 2,
y123 = (y12 + y23) / 2,
x234 = (x23 + x34) / 2,
y234 = (y23 + y34) / 2,
x1234 = (x123 + x234) / 2,
y1234 = (y123 + y234) / 2,
dx = x4 - x1,
dy = y4 - y1,
d2 = _abs((x2 - x4) * dy - (y2 - y4) * dx),
d3 = _abs((x3 - x4) * dy - (y3 - y4) * dx),
length;
if (!points) {
points = [x1, y1, x4, y4];
index = 2;
}
points.splice(index || points.length - 2, 0, x1234, y1234);
if ((d2 + d3) * (d2 + d3) > threshold * (dx * dx + dy * dy)) {
length = points.length;
bezierToPoints(x1, y1, x12, y12, x123, y123, x1234, y1234, threshold, points, index);
bezierToPoints(x1234, y1234, x234, y234, x34, y34, x4, y4, threshold, points, index + 2 + (points.length - length));
}
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,
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 (closed) {
points.push(nextX, nextY);
nextX = x;
nextY = y;
x = points[l - 2];
y = points[l - 1];
points.unshift(x, y);
l += 4;
}
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;
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));
if (x !== prevX || y !== prevY) {
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 = segment.length - 6;
}
return segment;
}
function pointToSegDist(x, y, x1, y1, x2, y2) {
var dx = x2 - x1,
dy = y2 - y1,
t;
if (dx || dy) {
t = ((x - x1) * dx + (y - y1) * dy) / (dx * dx + dy * dy);
if (t > 1) {
x1 = x2;
y1 = y2;
} else if (t > 0) {
x1 += dx * t;
y1 += dy * t;
}
}
return Math.pow(x - x1, 2) + Math.pow(y - y1, 2);
}
function simplifyStep(points, first, last, tolerance, simplified) {
var maxSqDist = tolerance,
firstX = points[first],
firstY = points[first + 1],
lastX = points[last],
lastY = points[last + 1],
index,
i,
d;
for (i = first + 2; i < last; i += 2) {
d = pointToSegDist(points[i], points[i + 1], firstX, firstY, lastX, lastY);
if (d > maxSqDist) {
index = i;
maxSqDist = d;
}
}
if (maxSqDist > tolerance) {
index - first > 2 && simplifyStep(points, first, index, tolerance, simplified);
simplified.push(points[index], points[index + 1]);
last - index > 2 && simplifyStep(points, index, last, tolerance, simplified);
}
}
function simplifyPoints(points, tolerance) {
var prevX = parseFloat(points[0]),
prevY = parseFloat(points[1]),
temp = [prevX, prevY],
l = points.length - 2,
i,
x,
y,
dx,
dy,
result,
last;
tolerance = Math.pow(tolerance || 1, 2);
for (i = 2; i < l; i += 2) {
x = parseFloat(points[i]);
y = parseFloat(points[i + 1]);
dx = prevX - x;
dy = prevY - y;
if (dx * dx + dy * dy > tolerance) {
temp.push(x, y);
prevX = x;
prevY = y;
}
}
temp.push(parseFloat(points[l]), parseFloat(points[l + 1]));
last = temp.length - 2;
result = [temp[0], temp[1]];
simplifyStep(temp, 0, last, tolerance, result);
result.push(temp[last], temp[last + 1]);
return result;
}
function getClosestProgressOnBezier(iterations, px, py, start, end, slices, x0, y0, x1, y1, x2, y2, x3, y3) {
var inc = (end - start) / slices,
best = 0,
t = start,
x,
y,
d,
dx,
dy,
inv;
_bestDistance = _largeNum;
while (t <= end) {
inv = 1 - t;
x = inv * inv * inv * x0 + 3 * inv * inv * t * x1 + 3 * inv * t * t * x2 + t * t * t * x3;
y = inv * inv * inv * y0 + 3 * inv * inv * t * y1 + 3 * inv * t * t * y2 + t * t * t * y3;
dx = x - px;
dy = y - py;
d = dx * dx + dy * dy;
if (d < _bestDistance) {
_bestDistance = d;
best = t;
}
t += inc;
}
return iterations > 1 ? getClosestProgressOnBezier(iterations - 1, px, py, Math.max(best - inc, 0), Math.min(best + inc, 1), slices, x0, y0, x1, y1, x2, y2, x3, y3) : best;
}
function getClosestData(rawPath, x, y, slices) {
var closest = {
j: 0,
i: 0,
t: 0
},
bestDistance = _largeNum,
i,
j,
t,
segment;
for (j = 0; j < rawPath.length; j++) {
segment = rawPath[j];
for (i = 0; i < segment.length; i += 6) {
t = getClosestProgressOnBezier(1, x, y, 0, 1, slices || 20, segment[i], segment[i + 1], segment[i + 2], segment[i + 3], segment[i + 4], segment[i + 5], segment[i + 6], segment[i + 7]);
if (bestDistance > _bestDistance) {
bestDistance = _bestDistance;
closest.j = j;
closest.i = i;
closest.t = t;
}
}
}
return closest;
}
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 _doc,
_win,
_docElement,
_body,
_divContainer,
_svgContainer,
_identityMatrix,
_gEl,
_transformProp = "transform",
_transformOriginProp = _transformProp + "Origin",
_hasOffsetBug,
_setDoc = function _setDoc(element) {
var doc = element.ownerDocument || element;
if (!(_transformProp in element.style) && "msTransform" in element.style) {
_transformProp = "msTransform";
_transformOriginProp = _transformProp + "Origin";
}
while (doc.parentNode && (doc = doc.parentNode)) {}
_win = window;
_identityMatrix = new Matrix2D();
if (doc) {
_doc = doc;
_docElement = doc.documentElement;
_body = doc.body;
_gEl = _doc.createElementNS("http://www.w3.org/2000/svg", "g");
_gEl.style.transform = "none";
var d1 = doc.createElement("div"),
d2 = doc.createElement("div"),
root = doc && (doc.body || doc.firstElementChild);
if (root && root.appendChild) {
root.appendChild(d1);
d1.appendChild(d2);
d1.setAttribute("style", "position:static;transform:translate3d(0,0,1px)");
_hasOffsetBug = d2.offsetParent !== d1;
root.removeChild(d1);
}
}
return doc;
},
_forceNonZeroScale = function _forceNonZeroScale(e) {
var a, cache;
while (e && e !== _body) {
cache = e._gsap;
cache && cache.uncache && cache.get(e, "x");
if (cache && !cache.scaleX && !cache.scaleY && cache.renderTransform) {
cache.scaleX = cache.scaleY = 1e-4;
cache.renderTransform(1, cache);
a ? a.push(cache) : a = [cache];
}
e = e.parentNode;
}
return a;
},
_svgTemps = [],
_divTemps = [],
_getDocScrollTop = function _getDocScrollTop() {
return _win.pageYOffset || _doc.scrollTop || _docElement.scrollTop || _body.scrollTop || 0;
},
_getDocScrollLeft = function _getDocScrollLeft() {
return _win.pageXOffset || _doc.scrollLeft || _docElement.scrollLeft || _body.scrollLeft || 0;
},
_svgOwner = function _svgOwner(element) {
return element.ownerSVGElement || ((element.tagName + "").toLowerCase() === "svg" ? element : null);
},
_isFixed = function _isFixed(element) {
if (_win.getComputedStyle(element).position === "fixed") {
return true;
}
element = element.parentNode;
if (element && element.nodeType === 1) {
return _isFixed(element);
}
},
_createSibling = function _createSibling(element, i) {
if (element.parentNode && (_doc || _setDoc(element))) {
var svg = _svgOwner(element),
ns = svg ? svg.getAttribute("xmlns") || "http://www.w3.org/2000/svg" : "http://www.w3.org/1999/xhtml",
type = svg ? i ? "rect" : "g" : "div",
x = i !== 2 ? 0 : 100,
y = i === 3 ? 100 : 0,
css = "position:absolute;display:block;pointer-events:none;margin:0;padding:0;",
e = _doc.createElementNS ? _doc.createElementNS(ns.replace(/^https/, "http"), type) : _doc.createElement(type);
if (i) {
if (!svg) {
if (!_divContainer) {
_divContainer = _createSibling(element);
_divContainer.style.cssText = css;
}
e.style.cssText = css + "width:0.1px;height:0.1px;top:" + y + "px;left:" + x + "px";
_divContainer.appendChild(e);
} else {
_svgContainer || (_svgContainer = _createSibling(element));
e.setAttribute("width", 0.01);
e.setAttribute("height", 0.01);
e.setAttribute("transform", "translate(" + x + "," + y + ")");
_svgContainer.appendChild(e);
}
}
return e;
}
throw "Need document and parent.";
},
_consolidate = function _consolidate(m) {
var c = new Matrix2D(),
i = 0;
for (; i < m.numberOfItems; i++) {
c.multiply(m.getItem(i).matrix);
}
return c;
},
_getCTM = function _getCTM(svg) {
var m = svg.getCTM(),
transform;
if (!m) {
transform = svg.style[_transformProp];
svg.style[_transformProp] = "none";
svg.appendChild(_gEl);
m = _gEl.getCTM();
svg.removeChild(_gEl);
transform ? svg.style[_transformProp] = transform : svg.style.removeProperty(_transformProp.replace(/([A-Z])/g, "-$1").toLowerCase());
}
return m || _identityMatrix.clone();
},
_placeSiblings = function _placeSiblings(element, adjustGOffset) {
var svg = _svgOwner(element),
isRootSVG = element === svg,
siblings = svg ? _svgTemps : _divTemps,
parent = element.parentNode,
appendToEl = parent && !svg && parent.shadowRoot && parent.shadowRoot.appendChild ? parent.shadowRoot : parent,
container,
m,
b,
x,
y,
cs;
if (element === _win) {
return element;
}
siblings.length || siblings.push(_createSibling(element, 1), _createSibling(element, 2), _createSibling(element, 3));
container = svg ? _svgContainer : _divContainer;
if (svg) {
if (isRootSVG) {
b = _getCTM(element);
x = -b.e / b.a;
y = -b.f / b.d;
m = _identityMatrix;
} else if (element.getBBox) {
b = element.getBBox();
m = element.transform ? element.transform.baseVal : {};
m = !m.numberOfItems ? _identityMatrix : m.numberOfItems > 1 ? _consolidate(m) : m.getItem(0).matrix;
x = m.a * b.x + m.c * b.y;
y = m.b * b.x + m.d * b.y;
} else {
m = new Matrix2D();
x = y = 0;
}
if (adjustGOffset && element.tagName.toLowerCase() === "g") {
x = y = 0;
}
(isRootSVG ? svg : parent).appendChild(container);
container.setAttribute("transform", "matrix(" + m.a + "," + m.b + "," + m.c + "," + m.d + "," + (m.e + x) + "," + (m.f + y) + ")");
} else {
x = y = 0;
if (_hasOffsetBug) {
m = element.offsetParent;
b = element;
while (b && (b = b.parentNode) && b !== m && b.parentNode) {
if ((_win.getComputedStyle(b)[_transformProp] + "").length > 4) {
x = b.offsetLeft;
y = b.offsetTop;
b = 0;
}
}
}
cs = _win.getComputedStyle(element);
if (cs.position !== "absolute" && cs.position !== "fixed") {
m = element.offsetParent;
while (parent && parent !== m) {
x += parent.scrollLeft || 0;
y += parent.scrollTop || 0;
parent = parent.parentNode;
}
}
b = container.style;
b.top = element.offsetTop - y + "px";
b.left = element.offsetLeft - x + "px";
b[_transformProp] = cs[_transformProp];
b[_transformOriginProp] = cs[_transformOriginProp];
b.position = cs.position === "fixed" ? "fixed" : "absolute";
appendToEl.appendChild(container);
}
return container;
},
_setMatrix = function _setMatrix(m, a, b, c, d, e, f) {
m.a = a;
m.b = b;
m.c = c;
m.d = d;
m.e = e;
m.f = f;
return m;
};
var Matrix2D = function () {
function Matrix2D(a, b, c, d, e, f) {
if (a === void 0) {
a = 1;
}
if (b === void 0) {
b = 0;
}
if (c === void 0) {
c = 0;
}
if (d === void 0) {
d = 1;
}
if (e === void 0) {
e = 0;
}
if (f === void 0) {
f = 0;
}
_setMatrix(this, a, b, c, d, e, f);
}
var _proto = Matrix2D.prototype;
_proto.inverse = function inverse() {
var a = this.a,
b = this.b,
c = this.c,
d = this.d,
e = this.e,
f = this.f,
determinant = a * d - b * c || 1e-10;
return _setMatrix(this, d / determinant, -b / determinant, -c / determinant, a / determinant, (c * f - d * e) / determinant, -(a * f - b * e) / determinant);
};
_proto.multiply = function multiply(matrix) {
var a = this.a,
b = this.b,
c = this.c,
d = this.d,
e = this.e,
f = this.f,
a2 = matrix.a,
b2 = matrix.c,
c2 = matrix.b,
d2 = matrix.d,
e2 = matrix.e,
f2 = matrix.f;
return _setMatrix(this, a2 * a + c2 * c, a2 * b + c2 * d, b2 * a + d2 * c, b2 * b + d2 * d, e + e2 * a + f2 * c, f + e2 * b + f2 * d);
};
_proto.clone = function clone() {
return new Matrix2D(this.a, this.b, this.c, this.d, this.e, this.f);
};
_proto.equals = function equals(matrix) {
var a = this.a,
b = this.b,
c = this.c,
d = this.d,
e = this.e,
f = this.f;
return a === matrix.a && b === matrix.b && c === matrix.c && d === matrix.d && e === matrix.e && f === matrix.f;
};
_proto.apply = function apply(point, decoratee) {
if (decoratee === void 0) {
decoratee = {};
}
var x = point.x,
y = point.y,
a = this.a,
b = this.b,
c = this.c,
d = this.d,
e = this.e,
f = this.f;
decoratee.x = x * a + y * c + e || 0;
decoratee.y = x * b + y * d + f || 0;
return decoratee;
};
return Matrix2D;
}();
function getGlobalMatrix(element, inverse, adjustGOffset, includeScrollInFixed) {
if (!element || !element.parentNode || (_doc || _setDoc(element)).documentElement === element) {
return new Matrix2D();
}
var zeroScales = _forceNonZeroScale(element),
svg = _svgOwner(element),
temps = svg ? _svgTemps : _divTemps,
container = _placeSiblings(element, adjustGOffset),
b1 = temps[0].getBoundingClientRect(),
b2 = temps[1].getBoundingClientRect(),
b3 = temps[2].getBoundingClientRect(),
parent = container.parentNode,
isFixed = !includeScrollInFixed && _isFixed(element),
m = new Matrix2D((b2.left - b1.left) / 100, (b2.top - b1.top) / 100, (b3.left - b1.left) / 100, (b3.top - b1.top) / 100, b1.left + (isFixed ? 0 : _getDocScrollLeft()), b1.top + (isFixed ? 0 : _getDocScrollTop()));
parent.removeChild(container);
if (zeroScales) {
b1 = zeroScales.length;
while (b1--) {
b2 = zeroScales[b1];
b2.scaleX = b2.scaleY = 0;
b2.renderTransform(1, b2);
}
}
return inverse ? m.inverse() : m;
}
var _numbersExp = /(?:(-)?\d*\.?\d*(?:e[\-+]?\d+)?)[0-9]/ig,
_doc$1,
_supportsPointer,
_win$1,
_body$1,
gsap,
_context,
_selectionColor = "#4e7fff",
_minimumMovement = 1,
_DEG2RAD$1 = Math.PI / 180,
_getTime = Date.now || function () {
return new Date().getTime();
},
_lastInteraction = 0,
_isPressed = 0,
_emptyFunc = function _emptyFunc() {
return false;
},
_interacted = function _interacted() {
return _lastInteraction = _getTime();
},
_CTRL,
_ALT,
_SHIFT,
_CMD,
_recentlyAddedAnchor,
_editingAxis = {},
_history = [],
_point = {},
_temp = [],
_comma = ",",
_selectedPaths = [],
_preventDefault = function _preventDefault(event) {
if (event.preventDefault) {
event.preventDefault();
if (event.preventManipulation) {
event.preventManipulation();
}
}
},
_createElement = function _createElement(type) {
return _doc$1.createElementNS ? _doc$1.createElementNS("http://www.w3.org/1999/xhtml", type) : _doc$1.createElement(type);
},
_createSVG = function _createSVG(type, container, attributes) {
var element = _doc$1.createElementNS("http://www.w3.org/2000/svg", type),
reg = /([a-z])([A-Z])/g,
p;
attributes = attributes || {};
attributes["class"] = attributes["class"] || "path-editor";
for (p in attributes) {
if (element.style[p] !== undefined) {
element.style[p] = attributes[p];
} else {
element.setAttributeNS(null, p.replace(reg, "$1-$2").toLowerCase(), attributes[p]);
}
}
container.appendChild(element);
return element;
},
_identityMatrixObject = {
matrix: new Matrix2D()
},
_getConsolidatedMatrix = function _getConsolidatedMatrix(target) {
return (target.transform && target.transform.baseVal.consolidate() || _identityMatrixObject).matrix;
},
_getConcatenatedTransforms = function _getConcatenatedTransforms(target) {
var m = _getConsolidatedMatrix(target),
owner = target.ownerSVGElement;
while ((target = target.parentNode) && target.ownerSVGElement === owner) {
m.multiply(_getConsolidatedMatrix(target));
}
return "matrix(" + m.a + "," + m.b + "," + m.c + "," + m.d + "," + m.e + "," + m.f + ")";
},
_addHistory = function _addHistory(pathEditor) {
var selectedIndexes = [],
a = pathEditor._selectedAnchors,
i;
for (i = 0; i < a.length; i++) {
selectedIndexes[i] = a[i].i;
}
_history.unshift({
path: pathEditor,
d: pathEditor.path.getAttribute("d"),
transform: pathEditor.path.getAttribute("transform") || "",
selectedIndexes: selectedIndexes
});
if (_history.length > 30) {
_history.length = 30;
}
},
_round$1 = function _round(value) {
return ~~(value * 1000 + (value < 0 ? -.5 : .5)) / 1000;
},
_getSquarePathData = function _getSquarePathData(size) {
size = _round$1(size);
return ["M-" + size, -size, size, -size, size, size, -size, size + "z"].join(_comma);
},
_getCirclePathData = function _getCirclePathData(size) {
var circ = 0.552284749831,
rcirc = _round$1(size * circ);
size = _round$1(size);
return "M" + size + ",0C" + [size, rcirc, rcirc, size, 0, size, -rcirc, size, -size, rcirc, -size, 0, -size, -rcirc, -rcirc, -size, 0, -size, rcirc, -size, size, -rcirc, size, 0].join(_comma) + "z";
},
_checkDeselect = function _checkDeselect(e) {
if (!e.target._gsSelection && !_isPressed && _getTime() - _lastInteraction > 100) {
var i = _selectedPaths.length;
while (--i > -1) {
_selectedPaths[i].deselect();
}
_selectedPaths.length = 0;
}
},
_tempDiv,
_touchEventLookup,
_isMultiTouching = 0,
_addListener = function _addListener(element, type, func, capture) {
if (element.addEventListener) {
var touchType = _touchEventLookup[type];
capture = capture || {
passive: false
};
element.addEventListener(touchType || type, func, capture);
if (touchType && type !== touchType && touchType.substr(0, 7) !== "pointer") {
element.addEventListener(type, func, capture);
}
} else if (element.attachEvent) {
element.attachEvent("on" + type, func);
}
},
_removeListener = function _removeListener(element, type, func) {
if (element.removeEventListener) {
var touchType = _touchEventLookup[type];
element.removeEventListener(touchType || type, func);
if (touchType && type !== touchType && touchType.substr(0, 7) !== "pointer") {
element.removeEventListener(type, func);
}
} else if (element.detachEvent) {
element.detachEvent("on" + type, func);
}
},
_hasTouchID = function _hasTouchID(list, ID) {
var i = list.length;
while (--i > -1) {
if (list[i].identifier === ID) {
return true;
}
}
return false;
},
_onMultiTouchDocumentEnd = function _onMultiTouchDocumentEnd(e) {
_isMultiTouching = e.touches && _dragCount < e.touches.length;
_removeListener(e.target, "touchend", _onMultiTouchDocumentEnd);
},
_onMultiTouchDocument = function _onMultiTouchDocument(e) {
_isMultiTouching = e.touches && _dragCount < e.touches.length;
_addListener(e.target, "touchend", _onMultiTouchDocumentEnd);
},
_bind = function _bind(func, scope) {
return function (e) {
return func.call(scope, e);
};
},
_callback = function _callback(type, self, param) {
var callback = self.vars[type];
if (callback) {
callback.call(self.vars.callbackScope || self, param || self);
}
return self;
},
_copyElement,
_resetSelection = function _resetSelection() {
_copyElement.style.display = "block";
_copyElement.select();
_copyElement.style.display = "none";
},
_coreInitted,
_initCore = function _initCore(core) {
_doc$1 = document;
_win$1 = window;
_body$1 = _doc$1.body;
gsap = gsap || core || _win$1.gsap || console.warn("Please gsap.registerPlugin(PathEditor)");
_context = gsap && gsap.core.context || function () {};
_tempDiv = _createElement("div");
_copyElement = _createElement("textarea");
_copyElement.style.display = "none";
_body$1 && _body$1.appendChild(_copyElement);
_touchEventLookup = function (types) {
var standard = types.split(","),
converted = (_tempDiv.onpointerdown !== undefined ? "pointerdown,pointermove,pointerup,pointercancel" : _tempDiv.onmspointerdown !== undefined ? "MSPointerDown,MSPointerMove,MSPointerUp,MSPointerCancel" : types).split(","),
obj = {},
i = 4;
while (--i > -1) {
obj[standard[i]] = converted[i];
obj[converted[i]] = standard[i];
}
return obj;
}("touchstart,touchmove,touchend,touchcancel");
SVGElement.prototype.getTransformToElement = SVGElement.prototype.getTransformToElement || function (e) {
return e.getScreenCTM().inverse().multiply(this.getScreenCTM());
};
_doc$1.addEventListener("keydown", function (e) {
var key = e.keyCode || e.which,
keyString = e.key || key,
i,
state,
a,
path;
if (keyString === "Shift" || key === 16) {
_SHIFT = true;
} else if (keyString === "Control" || key === 17) {
_CTRL = true;
} else if (keyString === "Meta" || key === 91) {
_CMD = true;
} else if (keyString === "Alt" || key === 18) {
_ALT = true;
i = _selectedPaths.length;
while (--i > -1) {
_selectedPaths[i]._onPressAlt();
}
} else if ((keyString === "z" || key === 90) && (_CTRL || _CMD) && _history.length > 1) {
_history.shift();
state = _history[0];
if (state) {
path = state.path;
path.path.setAttribute("d", state.d);
path.path.setAttribute("transform", state.transform);
path.init();
a = path._anchors;
for (i = 0; i < a.length; i++) {
if (state.selectedIndexes.indexOf(a[i].i) !== -1) {
path._selectedAnchors.push(a[i]);
}
}
path._updateAnchors();
path.update();
if (path.vars.onUndo) {
path.vars.onUndo.call(path);
}
}
} else if (keyString === "Delete" || keyString === "Backspace" || key === 8 || key === 46 || key === 63272 || key === "d" && (_CTRL || _CMD)) {
i = _selectedPaths.length;
while (--i > -1) {
_selectedPaths[i]._deleteSelectedAnchors();
}
} else if ((keyString === "a" || key === 65) && (_CMD || _CTRL)) {
i = _selectedPaths.length;
while (--i > -1) {
_selectedPaths[i].select(true);
}
}
}, true);
_doc$1.addEventListener("keyup", function (e) {
var key = e.key || e.keyCode || e.which;
if (key === "Shift" || key === 16) {
_SHIFT = false;
} else if (key === "Control" || key === 17) {
_CTRL = false;
} else if (key === "Meta" || key === 91) {
_CMD = false;
} else if (key === "Alt" || key === 18) {
_ALT = false;
var i = _selectedPaths.length;
while (--i > -1) {
_selectedPaths[i]._onReleaseAlt();
}
}
}, true);
_supportsPointer = !!_win$1.PointerEvent;
_addListener(_doc$1, "mouseup", _checkDeselect);
_addListener(_doc$1, "touchend", _checkDeselect);
_addListener(_doc$1, "touchcancel", _emptyFunc);
_addListener(_win$1, "touchmove", _emptyFunc);
_body$1 && _body$1.addEventListener("touchstart", _emptyFunc);
_coreInitted = 1;
},
_onPress = function _onPress(e) {
var self = this,
ctm = getGlobalMatrix(self.target.parentNode, true),
touchEventTarget,
temp;
this._matrix = this.target.transform.baseVal.getItem(0).matrix;
this._ctm = ctm;
if (_touchEventLookup[e.type]) {
touchEventTarget = e.type.indexOf("touch") !== -1 ? e.currentTarget || e.target : _doc$1;
_addListener(touchEventTarget, "touchend", self._onRelease);
_addListener(touchEventTarget, "touchmove", self._onMove);
_addListener(touchEventTarget, "touchcancel", self._onRelease);
_addListener(_doc$1, "touchstart", _onMultiTouchDocument);
_addListener(_win$1, "touchforcechange", _preventDefault);
} else {
touchEventTarget = null;
_addListener(_doc$1, "mousemove", self._onMove);
}
if (!_supportsPointer) {
_addListener(_doc$1, "mouseup", self._onRelease);
}
_preventDefault(e);
_resetSelection();
if (e.changedTouches) {
e = self.touch = e.changedTouches[0];
self.touchID = e.identifier;
} else if (e.pointerId) {
self.touchID = e.pointerId;
} else {
self.touch = self.touchID = null;
}
self._startPointerY = self.pointerY = e.pageY;
self._startPointerX = self.pointerX = e.pageX;
self._startElementX = self._matrix.e;
self._startElementY = self._matrix.f;
if (this._ctm.a === 1 && this._ctm.b === 0 && this._ctm.c === 0 && this._ctm.d === 1) {
this._ctm = null;
} else {
temp = self._startPointerX * this._ctm.a + self._startPointerY * this._ctm.c + this._ctm.e;
self._startPointerY = self._startPointerX * this._ctm.b + self._startPointerY * this._ctm.d + this._ctm.f;
self._startPointerX = temp;
}
self.isPressed = _isPressed = true;
self.touchEventTarget = touchEventTarget;
if (self.vars.onPress) {
self.vars.onPress.call(self.vars.callbackScope || self, self.pointerEvent);
}
},
_onMove = function _onMove(e) {
var self = this,
originalEvent = e,
touches,
i;
if (!self._enabled || _isMultiTouching || !self.isPressed || !e) {
return;
}
self.pointerEvent = e;
touches = e.changedTouches;
if (touches) {
e = touches[0];
if (e !== self.touch && e.identifier !== self.touchID) {
i = touches.length;
while (--i > -1 && (e = touches[i]).identifier !== self.touchID) {}
if (i < 0) {
return;
}
}
} else if (e.pointerId && self.touchID && e.pointerId !== self.touchID) {
return;
}
_preventDefault(originalEvent);
self.setPointerPosition(e.pageX, e.pageY);
if (self.vars.onDrag) {
self.vars.onDrag.call(self.vars.callbackScope || self, self.pointerEvent);
}
},
_onRelease = function _onRelease(e, force) {
var self = this;
if (!self._enabled || !self.isPressed || e && self.touchID != null && !force && (e.pointerId && e.pointerId !== self.touchID || e.changedTouches && !_hasTouchID(e.changedTouches, self.touchID))) {
return;
}
_interacted();
self.isPressed = _isPressed = false;
var originalEvent = e,
wasDragging = self.isDragging,
touchEventTarget = self.touchEventTarget,
touches,
i;
if (touchEventTarget) {
_removeListener(touchEventTarget, "touchend", self._onRelease);
_removeListener(touchEventTarget, "touchmove", self._onMove);
_removeListener(touchEventTarget, "touchcancel", self._onRelease);
_removeListener(_doc$1, "touchstart", _onMultiTouchDocument);
} else {
_removeListener(_doc$1, "mousemove", self._onMove);
}
if (!_supportsPointer) {
_removeListener(_doc$1, "mouseup", self._onRelease);
if (e && e.target) {
_removeListener(e.target, "mouseup", self._onRelease);
}
}
if (wasDragging) {
self.isDragging = false;
} else if (self.vars.onClick) {
self.vars.onClick.call(self.vars.callbackScope || self, originalEvent);
}
if (e) {
touches = e.changedTouches;
if (touches) {
e = touches[0];
if (e !== self.touch && e.identifier !== self.touchID) {
i = touches.length;
while (--i > -1 && (e = touches[i]).identifier !== self.touchID) {}
if (i < 0) {
return;
}
}
}
self.pointerEvent = originalEvent;
self.pointerX = e.pageX;
self.pointerY = e.pageY;
}
if (originalEvent && !wasDragging && self.vars.onDragRelease) {
self.vars.onDragRelease.call(self, self.pointerEvent);
} else {
if (originalEvent) {
_preventDefault(originalEvent);
}
if (self.vars.onRelease) {
self.vars.onRelease.call(self.vars.callbackScope || self, self.pointerEvent);
}
}
if (wasDragging && self.vars.onDragEnd) {
self.vars.onDragEnd.call(self.vars.callbackScope || self, self.pointerEvent);
}
return true;
},
_createSegmentAnchors = function _createSegmentAnchors(rawPath, j, editor, vars) {
var segment = rawPath[j],
l = segment.length - (segment.closed ? 6 : 0),
a = [],
i;
for (i = 0; i < l; i += 6) {
a.push(new Anchor(editor, rawPath, j, i, vars));
}
segment.closed && (a[0].isClosedStart = true);
return a;
},
_getLength = function _getLength(segment, i, i2) {
var x = segment[i2] - segment[i],
y = segment[i2 + 1] - segment[i + 1];
return Math.sqrt(x * x + y * y);
};
var DraggableSVG = function () {
function DraggableSVG(target, vars) {
this.target = typeof target === "string" ? _doc$1.querySelectorAll(target)[0] : target;
this.vars = vars || {};
this._onPress = _bind(_onPress, this);
this._onMove = _bind(_onMove, this);
this._onRelease = _bind(_onRelease, this);
this.target.setAttribute("transform", (this.target.getAttribute("transform") || "") + " translate(0,0)");
this._matrix = _getConsolidatedMatrix(this.target);
this.x = this._matrix.e;
this.y = this._matrix.f;
this.snap = vars.snap;
if (!isNaN(vars.maxX) || !isNaN(vars.minX)) {
this._bounds = 1;
this.maxX = +vars.maxX;
this.minX = +vars.minX;
} else {
this._bounds = 0;
}
this.enabled(true);
}
var _proto = DraggableSVG.prototype;
_proto.setPointerPosition = function setPointerPosition(pointerX, pointerY) {
var rnd = 1000,
xChange,
yChange,
x,
y,
temp;
this.pointerX = pointerX;
this.pointerY = pointerY;
if (this._ctm) {
temp = pointerX * this._ctm.a + pointerY * this._ctm.c + this._ctm.e;
pointerY = pointerX * this._ctm.b + pointerY * this._ctm.d + this._ctm.f;
pointerX = temp;
}
yChange = pointerY - this._startPointerY;
xChange = pointerX - this._startPointerX;
if (yChange < _minimumMovement && yChange > -_minimumMovement) {
yChange = 0;
}
if (xChange < _minimumMovement && xChange > -_minimumMovement) {
xChange = 0;
}
x = ((this._startElementX + xChange) * rnd | 0) / rnd;
y = ((this._startElementY + yChange) * rnd | 0) / rnd;
if (this.snap && !_SHIFT) {
_point.x = x;
_point.y = y;
this.snap.call(this, _point);
x = _point.x;
y = _point.y;
}
if (this.x !== x || this.y !== y) {
this._matrix.f = this.y = y;
this._matrix.e = this.x = x;
if (!this.isDragging && this.isPressed) {
this.isDragging = true;
_callback("onDragStart", this, this.pointerEvent);
}
}
};
_proto.enabled = function enabled(_enabled) {
if (!arguments.length) {
return this._enabled;
}
var dragging;
this._enabled = _enabled;
if (_enabled) {
if (!_supportsPointer) {
_addListener(this.target, "mousedown", this._onPress);
}
_addListener(this.target, "touchstart", this._onPress);
_addListener(this.target, "click", this._onClick, true);
} else {
dragging = this.isDragging;
_removeListener(this.target, "mousedown", this._onPress);
_removeListener(this.target, "touchstart", this._onPress);
_removeListener(_win$1, "touchforcechange", _preventDefault);
_removeListener(this.target, "click", this._onClick);
if (this.touchEventTarget) {
_removeListener(this.touchEventTarget, "touchcancel", this._onRelease);
_removeListener(this.touchEventTarget, "touchend", this._onRelease);
_removeListener(this.touchEventTarget, "touchmove", this._onMove);
}
_removeListener(_doc$1, "mouseup", this._onRelease);
_removeListener(_doc$1, "mousemove", this._onMove);
this.isDragging = this.isPressed = false;
if (dragging) {
_callback("onDragEnd", this, this.pointerEvent);
}
}
return this;
};
_proto.endDrag = function endDrag(e) {
this._onRelease(e);
};
return DraggableSVG;
}();
var Anchor = function () {
function Anchor(editor, rawPath, j, i, vars) {
this.editor = editor;
this.element = _createSVG("path", editor._selection, {
fill: _selectionColor,
stroke: _selectionColor,
strokeWidth: 2,
vectorEffect: "non-scaling-stroke"
});
this.update(rawPath, j, i);
this.element._gsSelection = true;
this.vars = vars || {};
this._draggable = new DraggableSVG(this.element, {
callbackScope: this,
onDrag: this.onDrag,
snap: this.vars.snap,
onPress: this.onPress,
onRelease: this.onRelease,
onClick: this.onClick,
onDragEnd: this.onDragEnd
});
}
var _proto2 = Anchor.prototype;
_proto2.onPress = function onPress() {
_callback("onPress", this);
};
_proto2.onClick = function onClick() {
_callback("onClick", this);
};
_proto2.onDrag = function onDrag() {
var s = this.segment;
this.vars.onDrag.call(this.vars.callbackScope || this, this, this._draggable.x - s[this.i], this._draggable.y - s[this.i + 1]);
};
_proto2.onDragEnd = function onDragEnd() {
_callback("onDragEnd", this);
};
_proto2.onRelease = function onRelease() {
_callback("onRelease", this);
};
_proto2.update = function update(rawPath, j, i) {
if (rawPath) {
this.rawPath = rawPath;
}
if (arguments.length <= 1) {
j = this.j;
i = this.i;
} else {
this.j = j;
this.i = i;
}
var prevSmooth = this.smooth,
segment = this.rawPath[j],
pi = i === 0 && segment.closed ? segment.length - 4 : i - 2;
this.segment = segment;
this.smooth = i > 0 && i < segment.length - 2 && Math.abs(Math.atan2(segment[i + 1] - segment[pi + 1], segment[i] - segment[pi]) - Math.atan2(segment[i + 3] - segment[i + 1], segment[i + 2] - segment[i])) < 0.09 ? 2 : 0;
if (this.smooth !== prevSmooth) {
this.element.setAttribute("d", this.smooth ? this.editor._circleHandle : this.editor._squareHandle);
}
this.element.setAttribute("transform", "translate(" + segment[i] + "," + segment[i + 1] + ")");
};
return Anchor;
}();
var PathEditor = function () {
function PathEditor(target, vars) {
vars = vars || {};
_coreInitted || _initCore();
this.vars = vars;
this.path = typeof target === "string" ? _doc$1.querySelectorAll(target)[0] : target;
this._g = _createSVG("g", this.path.ownerSVGElement, {
"class": "path-editor-g path-editor"
});
this._selectionHittest = _createSVG("path", this._g, {
stroke: "transparent",
strokeWidth: 16,
fill: "none",
vectorEffect: "non-scaling-stroke"
});
this._selection = vars._selection || _createSVG("g", this._g, {
"class": "path-editor-selection path-editor"
});
this._selectionPath = _createSVG("path", this._selection, {
stroke: _selectionColor,
strokeWidth: 2,
fill: "none",
vectorEffect: "non-scaling-stroke"
});
this._selectedAnchors = [];
this._line1 = _createSVG("polyline", this._selection, {
stroke: _selectionColor,
strokeWidth: 2,
vectorEffect: "n