fill-path.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. function decasteljau(points, t) {
  2. var left = [];
  3. var right = [];
  4. function recurse(points, t) {
  5. if (points.length === 1) {
  6. left.push(points[0]);
  7. right.push(points[0]);
  8. }
  9. else {
  10. var middlePoints = [];
  11. for (var i = 0; i < points.length - 1; i++) {
  12. if (i === 0) {
  13. left.push(points[0]);
  14. }
  15. if (i === points.length - 2) {
  16. right.push(points[i + 1]);
  17. }
  18. middlePoints[i] = [(1 - t) * points[i][0] + t * points[i + 1][0], (1 - t) * points[i][1] + t * points[i + 1][1]];
  19. }
  20. recurse(middlePoints, t);
  21. }
  22. }
  23. if (points.length) {
  24. recurse(points, t);
  25. }
  26. return { left: left, right: right.reverse() };
  27. }
  28. function splitCurve(start, end, count) {
  29. var points = [[start[1], start[2]]];
  30. count = count || 2;
  31. var segments = [];
  32. if (end[0] === 'A') {
  33. points.push(end[6]);
  34. points.push(end[7]);
  35. }
  36. else if (end[0] === 'C') {
  37. points.push([end[1], end[2]]);
  38. points.push([end[3], end[4]]);
  39. points.push([end[5], end[6]]);
  40. }
  41. else if (end[0] === 'S' || end[0] === 'Q') {
  42. points.push([end[1], end[2]]);
  43. points.push([end[3], end[4]]);
  44. }
  45. else {
  46. points.push([end[1], end[2]]);
  47. }
  48. var leftSegments = points;
  49. var t = 1 / count;
  50. for (var i = 0; i < count - 1; i++) {
  51. var rt = t / (1 - t * i);
  52. var split = decasteljau(leftSegments, rt);
  53. segments.push(split.left);
  54. leftSegments = split.right;
  55. }
  56. segments.push(leftSegments);
  57. var result = segments.map(function (segment) {
  58. var cmd = [];
  59. if (segment.length === 4) {
  60. cmd.push('C');
  61. cmd = cmd.concat(segment[2]);
  62. }
  63. if (segment.length >= 3) {
  64. if (segment.length === 3) {
  65. cmd.push('Q');
  66. }
  67. cmd = cmd.concat(segment[1]);
  68. }
  69. if (segment.length === 2) {
  70. cmd.push('L');
  71. }
  72. cmd = cmd.concat(segment[segment.length - 1]);
  73. return cmd;
  74. });
  75. return result;
  76. }
  77. function splitSegment(start, end, count) {
  78. if (count === 1) {
  79. return [[].concat(start)];
  80. }
  81. var segments = [];
  82. if (end[0] === 'L' || end[0] === 'C' || end[0] === 'Q') {
  83. segments = segments.concat(splitCurve(start, end, count));
  84. }
  85. else {
  86. var temp = [].concat(start);
  87. if (temp[0] === 'M') {
  88. temp[0] = 'L';
  89. }
  90. for (var i = 0; i <= count - 1; i++) {
  91. segments.push(temp);
  92. }
  93. }
  94. return segments;
  95. }
  96. export default function fillPath(source, target) {
  97. if (source.length === 1) {
  98. return source;
  99. }
  100. var sourceLen = source.length - 1;
  101. var targetLen = target.length - 1;
  102. var ratio = sourceLen / targetLen;
  103. var segmentsToFill = [];
  104. if (source.length === 1 && source[0][0] === 'M') {
  105. for (var i = 0; i < targetLen - sourceLen; i++) {
  106. source.push(source[0]);
  107. }
  108. return source;
  109. }
  110. for (var i = 0; i < targetLen; i++) {
  111. var index = Math.floor(ratio * i);
  112. segmentsToFill[index] = (segmentsToFill[index] || 0) + 1;
  113. }
  114. var filled = segmentsToFill.reduce(function (filled, count, i) {
  115. if (i === sourceLen) {
  116. return filled.concat(source[sourceLen]);
  117. }
  118. return filled.concat(splitSegment(source[i], source[i + 1], count));
  119. }, []);
  120. filled.unshift(source[0]);
  121. if (target[targetLen] === 'Z' || target[targetLen] === 'z') {
  122. filled.push('Z');
  123. }
  124. return filled;
  125. }
  126. //# sourceMappingURL=fill-path.js.map