ZigZagModifier.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import {
  2. extendPrototype,
  3. } from '../functionExtensions';
  4. import PropertyFactory from '../PropertyFactory';
  5. import shapePool from '../pooling/shape_pool';
  6. import {
  7. ShapeModifier,
  8. } from './ShapeModifiers';
  9. import { PolynomialBezier } from '../PolynomialBezier';
  10. function ZigZagModifier() {}
  11. extendPrototype([ShapeModifier], ZigZagModifier);
  12. ZigZagModifier.prototype.initModifierProperties = function (elem, data) {
  13. this.getValue = this.processKeys;
  14. this.amplitude = PropertyFactory.getProp(elem, data.s, 0, null, this);
  15. this.frequency = PropertyFactory.getProp(elem, data.r, 0, null, this);
  16. this.pointsType = PropertyFactory.getProp(elem, data.pt, 0, null, this);
  17. this._isAnimated = this.amplitude.effectsSequence.length !== 0 || this.frequency.effectsSequence.length !== 0 || this.pointsType.effectsSequence.length !== 0;
  18. };
  19. function setPoint(outputBezier, point, angle, direction, amplitude, outAmplitude, inAmplitude) {
  20. var angO = angle - Math.PI / 2;
  21. var angI = angle + Math.PI / 2;
  22. var px = point[0] + Math.cos(angle) * direction * amplitude;
  23. var py = point[1] - Math.sin(angle) * direction * amplitude;
  24. outputBezier.setTripleAt(
  25. px,
  26. py,
  27. px + Math.cos(angO) * outAmplitude,
  28. py - Math.sin(angO) * outAmplitude,
  29. px + Math.cos(angI) * inAmplitude,
  30. py - Math.sin(angI) * inAmplitude,
  31. outputBezier.length()
  32. );
  33. }
  34. function getPerpendicularVector(pt1, pt2) {
  35. var vector = [
  36. pt2[0] - pt1[0],
  37. pt2[1] - pt1[1],
  38. ];
  39. var rot = -Math.PI * 0.5;
  40. var rotatedVector = [
  41. Math.cos(rot) * vector[0] - Math.sin(rot) * vector[1],
  42. Math.sin(rot) * vector[0] + Math.cos(rot) * vector[1],
  43. ];
  44. return rotatedVector;
  45. }
  46. function getProjectingAngle(path, cur) {
  47. var prevIndex = cur === 0 ? path.length() - 1 : cur - 1;
  48. var nextIndex = (cur + 1) % path.length();
  49. var prevPoint = path.v[prevIndex];
  50. var nextPoint = path.v[nextIndex];
  51. var pVector = getPerpendicularVector(prevPoint, nextPoint);
  52. return Math.atan2(0, 1) - Math.atan2(pVector[1], pVector[0]);
  53. }
  54. function zigZagCorner(outputBezier, path, cur, amplitude, frequency, pointType, direction) {
  55. var angle = getProjectingAngle(path, cur);
  56. var point = path.v[cur % path._length];
  57. var prevPoint = path.v[cur === 0 ? path._length - 1 : cur - 1];
  58. var nextPoint = path.v[(cur + 1) % path._length];
  59. var prevDist = pointType === 2
  60. ? Math.sqrt(Math.pow(point[0] - prevPoint[0], 2) + Math.pow(point[1] - prevPoint[1], 2))
  61. : 0;
  62. var nextDist = pointType === 2
  63. ? Math.sqrt(Math.pow(point[0] - nextPoint[0], 2) + Math.pow(point[1] - nextPoint[1], 2))
  64. : 0;
  65. setPoint(
  66. outputBezier,
  67. path.v[cur % path._length],
  68. angle,
  69. direction,
  70. amplitude,
  71. nextDist / ((frequency + 1) * 2),
  72. prevDist / ((frequency + 1) * 2),
  73. pointType
  74. );
  75. }
  76. function zigZagSegment(outputBezier, segment, amplitude, frequency, pointType, direction) {
  77. for (var i = 0; i < frequency; i += 1) {
  78. var t = (i + 1) / (frequency + 1);
  79. var dist = pointType === 2
  80. ? Math.sqrt(Math.pow(segment.points[3][0] - segment.points[0][0], 2) + Math.pow(segment.points[3][1] - segment.points[0][1], 2))
  81. : 0;
  82. var angle = segment.normalAngle(t);
  83. var point = segment.point(t);
  84. setPoint(
  85. outputBezier,
  86. point,
  87. angle,
  88. direction,
  89. amplitude,
  90. dist / ((frequency + 1) * 2),
  91. dist / ((frequency + 1) * 2),
  92. pointType
  93. );
  94. direction = -direction;
  95. }
  96. return direction;
  97. }
  98. ZigZagModifier.prototype.processPath = function (path, amplitude, frequency, pointType) {
  99. var count = path._length;
  100. var clonedPath = shapePool.newElement();
  101. clonedPath.c = path.c;
  102. if (!path.c) {
  103. count -= 1;
  104. }
  105. if (count === 0) return clonedPath;
  106. var direction = -1;
  107. var segment = PolynomialBezier.shapeSegment(path, 0);
  108. zigZagCorner(clonedPath, path, 0, amplitude, frequency, pointType, direction);
  109. for (var i = 0; i < count; i += 1) {
  110. direction = zigZagSegment(clonedPath, segment, amplitude, frequency, pointType, -direction);
  111. if (i === count - 1 && !path.c) {
  112. segment = null;
  113. } else {
  114. segment = PolynomialBezier.shapeSegment(path, (i + 1) % count);
  115. }
  116. zigZagCorner(clonedPath, path, i + 1, amplitude, frequency, pointType, direction);
  117. }
  118. return clonedPath;
  119. };
  120. ZigZagModifier.prototype.processShapes = function (_isFirstFrame) {
  121. var shapePaths;
  122. var i;
  123. var len = this.shapes.length;
  124. var j;
  125. var jLen;
  126. var amplitude = this.amplitude.v;
  127. var frequency = Math.max(0, Math.round(this.frequency.v));
  128. var pointType = this.pointsType.v;
  129. if (amplitude !== 0) {
  130. var shapeData;
  131. var localShapeCollection;
  132. for (i = 0; i < len; i += 1) {
  133. shapeData = this.shapes[i];
  134. localShapeCollection = shapeData.localShapeCollection;
  135. if (!(!shapeData.shape._mdf && !this._mdf && !_isFirstFrame)) {
  136. localShapeCollection.releaseShapes();
  137. shapeData.shape._mdf = true;
  138. shapePaths = shapeData.shape.paths.shapes;
  139. jLen = shapeData.shape.paths._length;
  140. for (j = 0; j < jLen; j += 1) {
  141. localShapeCollection.addShape(this.processPath(shapePaths[j], amplitude, frequency, pointType));
  142. }
  143. }
  144. shapeData.shape.paths = shapeData.localShapeCollection;
  145. }
  146. }
  147. if (!this.dynamicProperties.length) {
  148. this._mdf = false;
  149. }
  150. };
  151. export default ZigZagModifier;