path-2-absolute.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import parsePathString from './parse-path-string';
  2. var REGEX_MD = /[a-z]/;
  3. function toSymmetry(p, c) {
  4. return [
  5. c[0] + (c[0] - p[0]),
  6. c[1] + (c[1] - p[1]),
  7. ];
  8. }
  9. export default function pathToAbsolute(pathString) {
  10. var pathArray = parsePathString(pathString);
  11. if (!pathArray || !pathArray.length) {
  12. return [
  13. ['M', 0, 0],
  14. ];
  15. }
  16. var needProcess = false; // 如果存在小写的命令或者 V,H,T,S 则需要处理
  17. for (var i = 0; i < pathArray.length; i++) {
  18. var cmd = pathArray[i][0];
  19. // 如果存在相对位置的命令,则中断返回
  20. if (REGEX_MD.test(cmd) || ['V', 'H', 'T', 'S'].indexOf(cmd) >= 0) {
  21. needProcess = true;
  22. break;
  23. }
  24. }
  25. // 如果不存在相对命令,则直接返回
  26. // 如果在业务上都写绝对路径,这种方式最快,仅做了一次检测
  27. if (!needProcess) {
  28. return pathArray;
  29. }
  30. var res = [];
  31. var x = 0;
  32. var y = 0;
  33. var mx = 0;
  34. var my = 0;
  35. var start = 0;
  36. var pa0;
  37. var dots;
  38. var first = pathArray[0];
  39. if (first[0] === 'M' || first[0] === 'm') {
  40. x = +first[1];
  41. y = +first[2];
  42. mx = x;
  43. my = y;
  44. start++;
  45. res[0] = ['M', x, y];
  46. }
  47. for (var i = start, ii = pathArray.length; i < ii; i++) {
  48. var pa = pathArray[i];
  49. var preParams = res[i - 1]; // 取前一个已经处理后的节点,否则会出现问题
  50. var r = [];
  51. var cmd = pa[0];
  52. var upCmd = cmd.toUpperCase();
  53. if (cmd !== upCmd) {
  54. r[0] = upCmd;
  55. switch (upCmd) {
  56. case 'A':
  57. r[1] = pa[1];
  58. r[2] = pa[2];
  59. r[3] = pa[3];
  60. r[4] = pa[4];
  61. r[5] = pa[5];
  62. r[6] = +pa[6] + x;
  63. r[7] = +pa[7] + y;
  64. break;
  65. case 'V':
  66. r[1] = +pa[1] + y;
  67. break;
  68. case 'H':
  69. r[1] = +pa[1] + x;
  70. break;
  71. case 'M':
  72. mx = +pa[1] + x;
  73. my = +pa[2] + y;
  74. r[1] = mx;
  75. r[2] = my;
  76. break; // for lint
  77. default:
  78. for (var j = 1, jj = pa.length; j < jj; j++) {
  79. r[j] = +pa[j] + ((j % 2) ? x : y);
  80. }
  81. }
  82. }
  83. else { // 如果本来已经大写,则不处理
  84. r = pathArray[i];
  85. }
  86. // 需要在外面统一做,同时处理 V,H,S,T 等特殊指令
  87. switch (upCmd) {
  88. case 'Z':
  89. x = +mx;
  90. y = +my;
  91. break;
  92. case 'H':
  93. x = r[1];
  94. r = ['L', x, y];
  95. break;
  96. case 'V':
  97. y = r[1];
  98. r = ['L', x, y];
  99. break;
  100. case 'T':
  101. x = r[1];
  102. y = r[2];
  103. // 以 x, y 为中心的,上一个控制点的对称点
  104. // 需要假设上一个节点的命令为 Q
  105. var symetricT = toSymmetry([preParams[1], preParams[2]], [preParams[3], preParams[4]]);
  106. r = ['Q', symetricT[0], symetricT[1], x, y];
  107. break;
  108. case 'S':
  109. x = r[r.length - 2];
  110. y = r[r.length - 1];
  111. // 以 x,y 为中心,取上一个控制点,
  112. // 需要假设上一个线段为 C 或者 S
  113. var length_1 = preParams.length;
  114. var symetricS = toSymmetry([preParams[length_1 - 4], preParams[length_1 - 3]], [preParams[length_1 - 2], preParams[length_1 - 1]]);
  115. r = ['C', symetricS[0], symetricS[1], r[1], r[2], x, y];
  116. break;
  117. case 'M':
  118. mx = r[r.length - 2];
  119. my = r[r.length - 1];
  120. break; // for lint
  121. default:
  122. x = r[r.length - 2];
  123. y = r[r.length - 1];
  124. }
  125. res.push(r);
  126. }
  127. return res;
  128. }
  129. //# sourceMappingURL=path-2-absolute.js.map