roundSector.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. import { isArray } from '../../core/util.js';
  2. var PI = Math.PI;
  3. var PI2 = PI * 2;
  4. var mathSin = Math.sin;
  5. var mathCos = Math.cos;
  6. var mathACos = Math.acos;
  7. var mathATan2 = Math.atan2;
  8. var mathAbs = Math.abs;
  9. var mathSqrt = Math.sqrt;
  10. var mathMax = Math.max;
  11. var mathMin = Math.min;
  12. var e = 1e-4;
  13. function intersect(x0, y0, x1, y1, x2, y2, x3, y3) {
  14. var dx10 = x1 - x0;
  15. var dy10 = y1 - y0;
  16. var dx32 = x3 - x2;
  17. var dy32 = y3 - y2;
  18. var t = dy32 * dx10 - dx32 * dy10;
  19. if (t * t < e) {
  20. return;
  21. }
  22. t = (dx32 * (y0 - y2) - dy32 * (x0 - x2)) / t;
  23. return [x0 + t * dx10, y0 + t * dy10];
  24. }
  25. function computeCornerTangents(x0, y0, x1, y1, radius, cr, clockwise) {
  26. var x01 = x0 - x1;
  27. var y01 = y0 - y1;
  28. var lo = (clockwise ? cr : -cr) / mathSqrt(x01 * x01 + y01 * y01);
  29. var ox = lo * y01;
  30. var oy = -lo * x01;
  31. var x11 = x0 + ox;
  32. var y11 = y0 + oy;
  33. var x10 = x1 + ox;
  34. var y10 = y1 + oy;
  35. var x00 = (x11 + x10) / 2;
  36. var y00 = (y11 + y10) / 2;
  37. var dx = x10 - x11;
  38. var dy = y10 - y11;
  39. var d2 = dx * dx + dy * dy;
  40. var r = radius - cr;
  41. var s = x11 * y10 - x10 * y11;
  42. var d = (dy < 0 ? -1 : 1) * mathSqrt(mathMax(0, r * r * d2 - s * s));
  43. var cx0 = (s * dy - dx * d) / d2;
  44. var cy0 = (-s * dx - dy * d) / d2;
  45. var cx1 = (s * dy + dx * d) / d2;
  46. var cy1 = (-s * dx + dy * d) / d2;
  47. var dx0 = cx0 - x00;
  48. var dy0 = cy0 - y00;
  49. var dx1 = cx1 - x00;
  50. var dy1 = cy1 - y00;
  51. if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) {
  52. cx0 = cx1;
  53. cy0 = cy1;
  54. }
  55. return {
  56. cx: cx0,
  57. cy: cy0,
  58. x0: -ox,
  59. y0: -oy,
  60. x1: cx0 * (radius / r - 1),
  61. y1: cy0 * (radius / r - 1)
  62. };
  63. }
  64. function normalizeCornerRadius(cr) {
  65. var arr;
  66. if (isArray(cr)) {
  67. var len = cr.length;
  68. if (!len) {
  69. return cr;
  70. }
  71. if (len === 1) {
  72. arr = [cr[0], cr[0], 0, 0];
  73. }
  74. else if (len === 2) {
  75. arr = [cr[0], cr[0], cr[1], cr[1]];
  76. }
  77. else if (len === 3) {
  78. arr = cr.concat(cr[2]);
  79. }
  80. else {
  81. arr = cr;
  82. }
  83. }
  84. else {
  85. arr = [cr, cr, cr, cr];
  86. }
  87. return arr;
  88. }
  89. export function buildPath(ctx, shape) {
  90. var _a;
  91. var radius = mathMax(shape.r, 0);
  92. var innerRadius = mathMax(shape.r0 || 0, 0);
  93. var hasRadius = radius > 0;
  94. var hasInnerRadius = innerRadius > 0;
  95. if (!hasRadius && !hasInnerRadius) {
  96. return;
  97. }
  98. if (!hasRadius) {
  99. radius = innerRadius;
  100. innerRadius = 0;
  101. }
  102. if (innerRadius > radius) {
  103. var tmp = radius;
  104. radius = innerRadius;
  105. innerRadius = tmp;
  106. }
  107. var startAngle = shape.startAngle, endAngle = shape.endAngle;
  108. if (isNaN(startAngle) || isNaN(endAngle)) {
  109. return;
  110. }
  111. var cx = shape.cx, cy = shape.cy;
  112. var clockwise = !!shape.clockwise;
  113. var arc = mathAbs(endAngle - startAngle);
  114. var mod = arc > PI2 && arc % PI2;
  115. mod > e && (arc = mod);
  116. if (!(radius > e)) {
  117. ctx.moveTo(cx, cy);
  118. }
  119. else if (arc > PI2 - e) {
  120. ctx.moveTo(cx + radius * mathCos(startAngle), cy + radius * mathSin(startAngle));
  121. ctx.arc(cx, cy, radius, startAngle, endAngle, !clockwise);
  122. if (innerRadius > e) {
  123. ctx.moveTo(cx + innerRadius * mathCos(endAngle), cy + innerRadius * mathSin(endAngle));
  124. ctx.arc(cx, cy, innerRadius, endAngle, startAngle, clockwise);
  125. }
  126. }
  127. else {
  128. var icrStart = void 0;
  129. var icrEnd = void 0;
  130. var ocrStart = void 0;
  131. var ocrEnd = void 0;
  132. var ocrs = void 0;
  133. var ocre = void 0;
  134. var icrs = void 0;
  135. var icre = void 0;
  136. var ocrMax = void 0;
  137. var icrMax = void 0;
  138. var limitedOcrMax = void 0;
  139. var limitedIcrMax = void 0;
  140. var xre = void 0;
  141. var yre = void 0;
  142. var xirs = void 0;
  143. var yirs = void 0;
  144. var xrs = radius * mathCos(startAngle);
  145. var yrs = radius * mathSin(startAngle);
  146. var xire = innerRadius * mathCos(endAngle);
  147. var yire = innerRadius * mathSin(endAngle);
  148. var hasArc = arc > e;
  149. if (hasArc) {
  150. var cornerRadius = shape.cornerRadius;
  151. if (cornerRadius) {
  152. _a = normalizeCornerRadius(cornerRadius), icrStart = _a[0], icrEnd = _a[1], ocrStart = _a[2], ocrEnd = _a[3];
  153. }
  154. var halfRd = mathAbs(radius - innerRadius) / 2;
  155. ocrs = mathMin(halfRd, ocrStart);
  156. ocre = mathMin(halfRd, ocrEnd);
  157. icrs = mathMin(halfRd, icrStart);
  158. icre = mathMin(halfRd, icrEnd);
  159. limitedOcrMax = ocrMax = mathMax(ocrs, ocre);
  160. limitedIcrMax = icrMax = mathMax(icrs, icre);
  161. if (ocrMax > e || icrMax > e) {
  162. xre = radius * mathCos(endAngle);
  163. yre = radius * mathSin(endAngle);
  164. xirs = innerRadius * mathCos(startAngle);
  165. yirs = innerRadius * mathSin(startAngle);
  166. if (arc < PI) {
  167. var it_1 = intersect(xrs, yrs, xirs, yirs, xre, yre, xire, yire);
  168. if (it_1) {
  169. var x0 = xrs - it_1[0];
  170. var y0 = yrs - it_1[1];
  171. var x1 = xre - it_1[0];
  172. var y1 = yre - it_1[1];
  173. var a = 1 / mathSin(mathACos((x0 * x1 + y0 * y1) / (mathSqrt(x0 * x0 + y0 * y0) * mathSqrt(x1 * x1 + y1 * y1))) / 2);
  174. var b = mathSqrt(it_1[0] * it_1[0] + it_1[1] * it_1[1]);
  175. limitedOcrMax = mathMin(ocrMax, (radius - b) / (a + 1));
  176. limitedIcrMax = mathMin(icrMax, (innerRadius - b) / (a - 1));
  177. }
  178. }
  179. }
  180. }
  181. if (!hasArc) {
  182. ctx.moveTo(cx + xrs, cy + yrs);
  183. }
  184. else if (limitedOcrMax > e) {
  185. var crStart = mathMin(ocrStart, limitedOcrMax);
  186. var crEnd = mathMin(ocrEnd, limitedOcrMax);
  187. var ct0 = computeCornerTangents(xirs, yirs, xrs, yrs, radius, crStart, clockwise);
  188. var ct1 = computeCornerTangents(xre, yre, xire, yire, radius, crEnd, clockwise);
  189. ctx.moveTo(cx + ct0.cx + ct0.x0, cy + ct0.cy + ct0.y0);
  190. if (limitedOcrMax < ocrMax && crStart === crEnd) {
  191. ctx.arc(cx + ct0.cx, cy + ct0.cy, limitedOcrMax, mathATan2(ct0.y0, ct0.x0), mathATan2(ct1.y0, ct1.x0), !clockwise);
  192. }
  193. else {
  194. crStart > 0 && ctx.arc(cx + ct0.cx, cy + ct0.cy, crStart, mathATan2(ct0.y0, ct0.x0), mathATan2(ct0.y1, ct0.x1), !clockwise);
  195. ctx.arc(cx, cy, radius, mathATan2(ct0.cy + ct0.y1, ct0.cx + ct0.x1), mathATan2(ct1.cy + ct1.y1, ct1.cx + ct1.x1), !clockwise);
  196. crEnd > 0 && ctx.arc(cx + ct1.cx, cy + ct1.cy, crEnd, mathATan2(ct1.y1, ct1.x1), mathATan2(ct1.y0, ct1.x0), !clockwise);
  197. }
  198. }
  199. else {
  200. ctx.moveTo(cx + xrs, cy + yrs);
  201. ctx.arc(cx, cy, radius, startAngle, endAngle, !clockwise);
  202. }
  203. if (!(innerRadius > e) || !hasArc) {
  204. ctx.lineTo(cx + xire, cy + yire);
  205. }
  206. else if (limitedIcrMax > e) {
  207. var crStart = mathMin(icrStart, limitedIcrMax);
  208. var crEnd = mathMin(icrEnd, limitedIcrMax);
  209. var ct0 = computeCornerTangents(xire, yire, xre, yre, innerRadius, -crEnd, clockwise);
  210. var ct1 = computeCornerTangents(xrs, yrs, xirs, yirs, innerRadius, -crStart, clockwise);
  211. ctx.lineTo(cx + ct0.cx + ct0.x0, cy + ct0.cy + ct0.y0);
  212. if (limitedIcrMax < icrMax && crStart === crEnd) {
  213. ctx.arc(cx + ct0.cx, cy + ct0.cy, limitedIcrMax, mathATan2(ct0.y0, ct0.x0), mathATan2(ct1.y0, ct1.x0), !clockwise);
  214. }
  215. else {
  216. crEnd > 0 && ctx.arc(cx + ct0.cx, cy + ct0.cy, crEnd, mathATan2(ct0.y0, ct0.x0), mathATan2(ct0.y1, ct0.x1), !clockwise);
  217. ctx.arc(cx, cy, innerRadius, mathATan2(ct0.cy + ct0.y1, ct0.cx + ct0.x1), mathATan2(ct1.cy + ct1.y1, ct1.cx + ct1.x1), clockwise);
  218. crStart > 0 && ctx.arc(cx + ct1.cx, cy + ct1.cy, crStart, mathATan2(ct1.y1, ct1.x1), mathATan2(ct1.y0, ct1.x0), !clockwise);
  219. }
  220. }
  221. else {
  222. ctx.lineTo(cx + xire, cy + yire);
  223. ctx.arc(cx, cy, innerRadius, endAngle, startAngle, clockwise);
  224. }
  225. }
  226. ctx.closePath();
  227. }