path-2-segments.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. var get_arc_params_1 = require("./get-arc-params");
  4. var get_arc_params_2 = require("./get-arc-params");
  5. var parse_path_1 = require("./parse-path");
  6. // 点对称
  7. function toSymmetry(point, center) {
  8. return [center[0] + (center[0] - point[0]), center[1] + (center[1] - point[1])];
  9. }
  10. function getSegments(path) {
  11. path = parse_path_1.default(path);
  12. var segments = [];
  13. var currentPoint = null; // 当前图形
  14. var nextParams = null; // 下一节点的 path 参数
  15. var startMovePoint = null; // 开始 M 的点,可能会有多个
  16. var lastStartMovePointIndex = 0; // 最近一个开始点 M 的索引
  17. var count = path.length;
  18. for (var i = 0; i < count; i++) {
  19. var params = path[i];
  20. nextParams = path[i + 1];
  21. var command = params[0];
  22. // 数学定义上的参数,便于后面的计算
  23. var segment = {
  24. command: command,
  25. prePoint: currentPoint,
  26. params: params,
  27. startTangent: null,
  28. endTangent: null,
  29. };
  30. switch (command) {
  31. case 'M':
  32. startMovePoint = [params[1], params[2]];
  33. lastStartMovePointIndex = i;
  34. break;
  35. case 'A':
  36. var arcParams = get_arc_params_1.default(currentPoint, params);
  37. segment['arcParams'] = arcParams;
  38. break;
  39. default:
  40. break;
  41. }
  42. if (command === 'Z') {
  43. // 有了 Z 后,当前节点从开始 M 的点开始
  44. currentPoint = startMovePoint;
  45. // 如果当前点的命令为 Z,相当于当前点为最近一个 M 点,则下一个点直接指向最近一个 M 点的下一个点
  46. nextParams = path[lastStartMovePointIndex + 1];
  47. }
  48. else {
  49. var len = params.length;
  50. currentPoint = [params[len - 2], params[len - 1]];
  51. }
  52. if (nextParams && nextParams[0] === 'Z') {
  53. // 如果下一个点的命令为 Z,则下一个点直接指向最近一个 M 点
  54. nextParams = path[lastStartMovePointIndex];
  55. if (segments[lastStartMovePointIndex]) {
  56. // 如果下一个点的命令为 Z,则最近一个 M 点的前一个点为当前点
  57. segments[lastStartMovePointIndex].prePoint = currentPoint;
  58. }
  59. }
  60. segment['currentPoint'] = currentPoint;
  61. // 如果当前点与最近一个 M 点相同,则最近一个 M 点的前一个点为当前点的前一个点
  62. if (segments[lastStartMovePointIndex] &&
  63. get_arc_params_2.isSamePoint(currentPoint, segments[lastStartMovePointIndex].currentPoint)) {
  64. segments[lastStartMovePointIndex].prePoint = segment.prePoint;
  65. }
  66. var nextPoint = nextParams ? [nextParams[nextParams.length - 2], nextParams[nextParams.length - 1]] : null;
  67. segment['nextPoint'] = nextPoint;
  68. // Add startTangent and endTangent
  69. var prePoint = segment.prePoint;
  70. if (['L', 'H', 'V'].includes(command)) {
  71. segment.startTangent = [prePoint[0] - currentPoint[0], prePoint[1] - currentPoint[1]];
  72. segment.endTangent = [currentPoint[0] - prePoint[0], currentPoint[1] - prePoint[1]];
  73. }
  74. else if (command === 'Q') {
  75. // 二次贝塞尔曲线只有一个控制点
  76. var cp = [params[1], params[2]];
  77. // 二次贝塞尔曲线的终点为 currentPoint
  78. segment.startTangent = [prePoint[0] - cp[0], prePoint[1] - cp[1]];
  79. segment.endTangent = [currentPoint[0] - cp[0], currentPoint[1] - cp[1]];
  80. }
  81. else if (command === 'T') {
  82. var preSegment = segments[i - 1];
  83. var cp = toSymmetry(preSegment.currentPoint, prePoint);
  84. if (preSegment.command === 'Q') {
  85. segment.command = 'Q';
  86. segment.startTangent = [prePoint[0] - cp[0], prePoint[1] - cp[1]];
  87. segment.endTangent = [currentPoint[0] - cp[0], currentPoint[1] - cp[1]];
  88. }
  89. else {
  90. segment.command = 'TL';
  91. segment.startTangent = [prePoint[0] - currentPoint[0], prePoint[1] - currentPoint[1]];
  92. segment.endTangent = [currentPoint[0] - prePoint[0], currentPoint[1] - prePoint[1]];
  93. }
  94. }
  95. else if (command === 'C') {
  96. // 三次贝塞尔曲线有两个控制点
  97. var cp1 = [params[1], params[2]];
  98. var cp2 = [params[3], params[4]];
  99. segment.startTangent = [prePoint[0] - cp1[0], prePoint[1] - cp1[1]];
  100. segment.endTangent = [currentPoint[0] - cp2[0], currentPoint[1] - cp2[1]];
  101. // horizontal line, eg. ['C', 100, 100, 100, 100, 200, 200]
  102. if (segment.startTangent[0] === 0 && segment.startTangent[1] === 0) {
  103. segment.startTangent = [cp1[0] - cp2[0], cp1[1] - cp2[1]];
  104. }
  105. if (segment.endTangent[0] === 0 && segment.endTangent[1] === 0) {
  106. segment.endTangent = [cp2[0] - cp1[0], cp2[1] - cp1[1]];
  107. }
  108. }
  109. else if (command === 'S') {
  110. var preSegment = segments[i - 1];
  111. var cp1 = toSymmetry(preSegment.currentPoint, prePoint);
  112. var cp2 = [params[1], params[2]];
  113. if (preSegment.command === 'C') {
  114. segment.command = 'C'; // 将 S 命令变换为 C 命令
  115. segment.startTangent = [prePoint[0] - cp1[0], prePoint[1] - cp1[1]];
  116. segment.endTangent = [currentPoint[0] - cp2[0], currentPoint[1] - cp2[1]];
  117. }
  118. else {
  119. segment.command = 'SQ'; // 将 S 命令变换为 SQ 命令
  120. segment.startTangent = [prePoint[0] - cp2[0], prePoint[1] - cp2[1]];
  121. segment.endTangent = [currentPoint[0] - cp2[0], currentPoint[1] - cp2[1]];
  122. }
  123. }
  124. else if (command === 'A') {
  125. var d = 0.001;
  126. var _a = segment['arcParams'] || {}, _b = _a.cx, cx = _b === void 0 ? 0 : _b, _c = _a.cy, cy = _c === void 0 ? 0 : _c, _d = _a.rx, rx = _d === void 0 ? 0 : _d, _e = _a.ry, ry = _e === void 0 ? 0 : _e, _f = _a.sweepFlag, sweepFlag = _f === void 0 ? 0 : _f, _g = _a.startAngle, startAngle = _g === void 0 ? 0 : _g, _h = _a.endAngle, endAngle = _h === void 0 ? 0 : _h;
  127. if (sweepFlag === 0) {
  128. d *= -1;
  129. }
  130. var dx1 = rx * Math.cos(startAngle - d) + cx;
  131. var dy1 = ry * Math.sin(startAngle - d) + cy;
  132. segment.startTangent = [dx1 - startMovePoint[0], dy1 - startMovePoint[1]];
  133. var dx2 = rx * Math.cos(startAngle + endAngle + d) + cx;
  134. var dy2 = ry * Math.sin(startAngle + endAngle - d) + cy;
  135. segment.endTangent = [prePoint[0] - dx2, prePoint[1] - dy2];
  136. }
  137. segments.push(segment);
  138. }
  139. return segments;
  140. }
  141. exports.default = getSegments;
  142. //# sourceMappingURL=path-2-segments.js.map