UNPKG

lottie-web

Version:

After Effects plugin for exporting animations to SVG + JavaScript or canvas + JavaScript

175 lines (151 loc) 5.38 kB
import { extendPrototype, } from '../functionExtensions'; import PropertyFactory from '../PropertyFactory'; import shapePool from '../pooling/shape_pool'; import { ShapeModifier, } from './ShapeModifiers'; import { PolynomialBezier } from '../PolynomialBezier'; function ZigZagModifier() {} extendPrototype([ShapeModifier], ZigZagModifier); ZigZagModifier.prototype.initModifierProperties = function (elem, data) { 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.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 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 + Math.cos(angO) * outAmplitude, py - Math.sin(angO) * outAmplitude, px + Math.cos(angI) * inAmplitude, py - Math.sin(angI) * inAmplitude, outputBezier.length() ); } 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); setPoint( outputBezier, point, angle, direction, amplitude, dist / ((frequency + 1) * 2), dist / ((frequency + 1) * 2), pointType ); direction = -direction; } return direction; } ZigZagModifier.prototype.processPath = function (path, amplitude, frequency, pointType) { var count = path._length; var clonedPath = shapePool.newElement(); clonedPath.c = path.c; if (!path.c) { count -= 1; } if (count === 0) return clonedPath; var direction = -1; var segment = PolynomialBezier.shapeSegment(path, 0); zigZagCorner(clonedPath, path, 0, amplitude, frequency, pointType, direction); for (var i = 0; i < count; i += 1) { direction = zigZagSegment(clonedPath, segment, amplitude, frequency, pointType, -direction); if (i === count - 1 && !path.c) { segment = null; } else { segment = PolynomialBezier.shapeSegment(path, (i + 1) % count); } zigZagCorner(clonedPath, path, i + 1, amplitude, frequency, pointType, direction); } return clonedPath; }; ZigZagModifier.prototype.processShapes = function (_isFirstFrame) { var shapePaths; var i; var len = this.shapes.length; var j; 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; var localShapeCollection; for (i = 0; i < len; i += 1) { shapeData = this.shapes[i]; localShapeCollection = shapeData.localShapeCollection; if (!(!shapeData.shape._mdf && !this._mdf && !_isFirstFrame)) { localShapeCollection.releaseShapes(); shapeData.shape._mdf = true; 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, pointType)); } } shapeData.shape.paths = shapeData.localShapeCollection; } } if (!this.dynamicProperties.length) { this._mdf = false; } }; export default ZigZagModifier;