Merge branch 'master' of github.com:airbnb/lottie-web
diff --git a/player/js/utils/shapes/ZigZagModifier.js b/player/js/utils/shapes/ZigZagModifier.js
index 6afbb93..f84538b 100644
--- a/player/js/utils/shapes/ZigZagModifier.js
+++ b/player/js/utils/shapes/ZigZagModifier.js
@@ -14,44 +14,93 @@
this.getValue = this.processKeys;
this.amplitude = PropertyFactory.getProp(elem, data.s, 0, null, this);
this.frequency = PropertyFactory.getProp(elem, data.r, 0, null, this);
- this._isAnimated = this.amplitude.effectsSequence.length !== 0 && this.frequency.effectsSequence.length !== 0;
+ this.pointsType = PropertyFactory.getProp(elem, data.pt, 0, null, this);
+ this._isAnimated = this.amplitude.effectsSequence.length !== 0 || this.frequency.effectsSequence.length !== 0 || this.pointsType.effectsSequence.length !== 0;
};
-function angleMean(a, b) {
- if (Math.abs(a - b) > Math.PI) return (a + b) / 2 + Math.PI;
-
- return (a + b) / 2;
-}
-
-function zigZagCorner(outputBezier, segmentBefore, segmentAfter, amplitude, direction) {
- var point;
- var angle;
-
- if (!segmentBefore) {
- point = segmentAfter.points[0];
- angle = segmentAfter.normalAngle(0);
- } else if (!segmentAfter) {
- point = segmentBefore.points[3];
- angle = segmentBefore.normalAngle(1);
- } else {
- point = segmentAfter.points[0];
- angle = angleMean(segmentAfter.normalAngle(0), segmentBefore.normalAngle(1));
- }
-
+function setPoint(outputBezier, point, angle, direction, amplitude, outAmplitude, inAmplitude) {
+ var angO = angle - Math.PI / 2;
+ var angI = angle + Math.PI / 2;
var px = point[0] + Math.cos(angle) * direction * amplitude;
var py = point[1] - Math.sin(angle) * direction * amplitude;
- outputBezier.setTripleAt(px, py, px, py, px, py, outputBezier.length());
+
+ outputBezier.setTripleAt(
+ px,
+ py,
+ px + Math.cos(angO) * outAmplitude,
+ py - Math.sin(angO) * outAmplitude,
+ px + Math.cos(angI) * inAmplitude,
+ py - Math.sin(angI) * inAmplitude,
+ outputBezier.length()
+ );
}
-function zigZagSegment(outputBezier, segment, amplitude, frequency, direction) {
+function getPerpendicularVector(pt1, pt2) {
+ var vector = [
+ pt2[0] - pt1[0],
+ pt2[1] - pt1[1],
+ ];
+ var rot = -Math.PI * 0.5;
+ var rotatedVector = [
+ Math.cos(rot) * vector[0] - Math.sin(rot) * vector[1],
+ Math.sin(rot) * vector[0] + Math.cos(rot) * vector[1],
+ ];
+ return rotatedVector;
+}
+
+function getProjectingAngle(path, cur) {
+ var prevIndex = cur === 0 ? path.length() - 1 : cur - 1;
+ var nextIndex = (cur + 1) % path.length();
+ var prevPoint = path.v[prevIndex];
+ var nextPoint = path.v[nextIndex];
+ var pVector = getPerpendicularVector(prevPoint, nextPoint);
+ return Math.atan2(0, 1) - Math.atan2(pVector[1], pVector[0]);
+}
+
+function zigZagCorner(outputBezier, path, cur, amplitude, frequency, pointType, direction) {
+ var angle = getProjectingAngle(path, cur);
+ var point = path.v[cur % path._length];
+ var prevPoint = path.v[cur === 0 ? path._length - 1 : cur - 1];
+ var nextPoint = path.v[(cur + 1) % path._length];
+ var prevDist = pointType === 2
+ ? Math.sqrt(Math.pow(point[0] - prevPoint[0], 2) + Math.pow(point[1] - prevPoint[1], 2))
+ : 0;
+ var nextDist = pointType === 2
+ ? Math.sqrt(Math.pow(point[0] - nextPoint[0], 2) + Math.pow(point[1] - nextPoint[1], 2))
+ : 0;
+
+ setPoint(
+ outputBezier,
+ path.v[cur % path._length],
+ angle,
+ direction,
+ amplitude,
+ nextDist / ((frequency + 1) * 2),
+ prevDist / ((frequency + 1) * 2),
+ pointType
+ );
+}
+
+function zigZagSegment(outputBezier, segment, amplitude, frequency, pointType, direction) {
for (var i = 0; i < frequency; i += 1) {
var t = (i + 1) / (frequency + 1);
+
+ var dist = pointType === 2
+ ? Math.sqrt(Math.pow(segment.points[3][0] - segment.points[0][0], 2) + Math.pow(segment.points[3][1] - segment.points[0][1], 2))
+ : 0;
+
var angle = segment.normalAngle(t);
var point = segment.point(t);
- var px = point[0] + Math.cos(angle) * direction * amplitude;
- var py = point[1] - Math.sin(angle) * direction * amplitude;
-
- outputBezier.setTripleAt(px, py, px, py, px, py, outputBezier.length());
+ setPoint(
+ outputBezier,
+ point,
+ angle,
+ direction,
+ amplitude,
+ dist / ((frequency + 1) * 2),
+ dist / ((frequency + 1) * 2),
+ pointType
+ );
direction = -direction;
}
@@ -59,7 +108,7 @@
return direction;
}
-ZigZagModifier.prototype.processPath = function (path, amplitude, frequency) {
+ZigZagModifier.prototype.processPath = function (path, amplitude, frequency, pointType) {
var count = path._length;
var clonedPath = shapePool.newElement();
clonedPath.c = path.c;
@@ -71,23 +120,19 @@
if (count === 0) return clonedPath;
var direction = -1;
- var segment = path.c ? PolynomialBezier.shapeSegment(path, count - 1) : null;
- var nextSegment = PolynomialBezier.shapeSegment(path, 0);
-
- zigZagCorner(clonedPath, segment, nextSegment, amplitude, -1);
+ var segment = PolynomialBezier.shapeSegment(path, 0);
+ zigZagCorner(clonedPath, path, 0, amplitude, frequency, pointType, direction);
for (var i = 0; i < count; i += 1) {
- segment = nextSegment;
-
- direction = zigZagSegment(clonedPath, segment, amplitude, frequency, -direction);
+ direction = zigZagSegment(clonedPath, segment, amplitude, frequency, pointType, -direction);
if (i === count - 1 && !path.c) {
- nextSegment = null;
+ segment = null;
} else {
- nextSegment = PolynomialBezier.shapeSegment(path, (i + 1) % count);
+ segment = PolynomialBezier.shapeSegment(path, (i + 1) % count);
}
- zigZagCorner(clonedPath, segment, nextSegment, amplitude, direction);
+ zigZagCorner(clonedPath, path, i + 1, amplitude, frequency, pointType, direction);
}
return clonedPath;
@@ -101,6 +146,7 @@
var jLen;
var amplitude = this.amplitude.v;
var frequency = Math.max(0, Math.round(this.frequency.v));
+ var pointType = this.pointsType.v;
if (amplitude !== 0) {
var shapeData;
@@ -114,7 +160,7 @@
shapePaths = shapeData.shape.paths.shapes;
jLen = shapeData.shape.paths._length;
for (j = 0; j < jLen; j += 1) {
- localShapeCollection.addShape(this.processPath(shapePaths[j], amplitude, frequency));
+ localShapeCollection.addShape(this.processPath(shapePaths[j], amplitude, frequency, pointType));
}
}
shapeData.shape.paths = shapeData.localShapeCollection;