advance.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. var __rest = (this && this.__rest) || function (s, e) {
  2. var t = {};
  3. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
  4. t[p] = s[p];
  5. if (s != null && typeof Object.getOwnPropertySymbols === "function")
  6. for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
  7. if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
  8. t[p[i]] = s[p[i]];
  9. }
  10. return t;
  11. };
  12. import { Marker } from '@antv/gui';
  13. import { line } from 'd3-shape';
  14. import { createElement } from '../../utils/createElement';
  15. import { applyStyle } from '../utils';
  16. import { subObject } from '../../utils/helper';
  17. import { select } from '../../utils/selection';
  18. import { dist } from '../../utils/vector';
  19. function getConnectorPoint(shape) {
  20. const { min: [x0, y0], max: [x1, y1], } = shape.getLocalBounds();
  21. let x = 0;
  22. let y = 0;
  23. if (x0 > 0)
  24. x = x0;
  25. if (x1 < 0)
  26. x = x1;
  27. if (y0 > 0)
  28. y = y0;
  29. if (y1 < 0)
  30. y = y1;
  31. return [x, y];
  32. }
  33. function inferBackgroundBounds(textShape, padding = []) {
  34. const [top = 0, right = 0, bottom = top, left = right] = padding;
  35. const container = textShape.parentNode;
  36. const angle = container.getEulerAngles();
  37. container.setEulerAngles(0);
  38. const { min, halfExtents } = textShape.getLocalBounds();
  39. const [x, y] = min;
  40. const [hw, hh] = halfExtents;
  41. container.setEulerAngles(angle);
  42. return {
  43. x: x - left,
  44. y: y - top,
  45. width: hw * 2 + left + right,
  46. height: hh * 2 + top + bottom,
  47. };
  48. }
  49. const cos = (p0, p1, p2) => {
  50. const a = dist(p0, p1);
  51. const b = dist(p1, p2);
  52. const c = dist(p2, p0);
  53. return (Math.pow(a, 2) + Math.pow(b, 2) - Math.pow(c, 2)) / (2 * a * b);
  54. };
  55. function inferConnectorPath(shape, points, controlPoints, coordCenter) {
  56. const [[x0, y0], [x1, y1]] = points;
  57. const [x, y] = getConnectorPoint(shape);
  58. // Straight connector line.
  59. if (x0 === x1 && y0 === y1) {
  60. return line()([
  61. [0, 0],
  62. [x, y],
  63. ]);
  64. }
  65. const P = [[x0 - x1, y0 - y1]].concat(controlPoints.length ? controlPoints : [0, 0]);
  66. const p0 = [coordCenter[0] - x1, coordCenter[1] - y1];
  67. const [p1, p2] = P;
  68. // If angle is smaller than 90, which will cause connector overlap with element.
  69. if (cos(p0, p1, p2) > 0) {
  70. const x2 = (() => {
  71. const { min, max } = shape.getLocalBounds();
  72. // A(x1,y2) perpendicular to B(x2,y2) => x1*x2 + y1*y2 = 0
  73. const vx = p1[0] + ((p1[1] - p0[1]) * (p1[1] - 0)) / (p1[0] - p0[0]);
  74. if (max[0] < p0[0])
  75. return Math.min(max[0], vx);
  76. return Math.max(min[0], vx);
  77. })();
  78. P.splice(1, 1, [x2, 0]);
  79. }
  80. return line()(P);
  81. }
  82. export const Advance = createElement((g) => {
  83. const _a = g.attributes, {
  84. // Do not pass className
  85. class: className, transform, rotate, labelTransform, labelTransformOrigin, x, y, x0 = x, y0 = y, background, connector, startMarker, endMarker, coordCenter } = _a, rest = __rest(_a, ["class", "transform", "rotate", "labelTransform", "labelTransformOrigin", "x", "y", "x0", "y0", "background", "connector", "startMarker", "endMarker", "coordCenter"]);
  86. const _b = subObject(rest, 'background'), { padding } = _b, backgroundStyle = __rest(_b, ["padding"]);
  87. const _c = subObject(rest, 'connector'), { points = [] } = _c, connectorStyle = __rest(_c, ["points"]);
  88. const endPoints = [
  89. [+x0, +y0],
  90. [+x, +y],
  91. ];
  92. const shape1 = select(g)
  93. .maybeAppend('text', 'text')
  94. .style('zIndex', 0)
  95. .call(applyStyle, Object.assign({ textBaseline: 'middle', transform: labelTransform, transformOrigin: labelTransformOrigin }, rest))
  96. .node();
  97. const shape2 = select(g)
  98. .maybeAppend('background', 'rect')
  99. .style('zIndex', -1)
  100. .call(applyStyle, inferBackgroundBounds(shape1, padding))
  101. .call(applyStyle, background ? backgroundStyle : {})
  102. .node();
  103. const connectorPath = inferConnectorPath(shape2, endPoints, points, coordCenter);
  104. const markerStart = startMarker &&
  105. new Marker({
  106. id: 'startMarker',
  107. style: Object.assign({ x: 0, y: 0 }, subObject(rest, 'startMarker')),
  108. });
  109. const markerEnd = endMarker &&
  110. new Marker({
  111. id: 'endMarker',
  112. style: Object.assign({ x: 0, y: 0 }, subObject(rest, 'endMarker')),
  113. });
  114. select(g)
  115. .maybeAppend('connector', 'path')
  116. .style('zIndex', 0)
  117. .style('path', connectorPath)
  118. .style('markerStart', markerStart)
  119. .style('markerEnd', markerEnd)
  120. .call(applyStyle, connector ? connectorStyle : {});
  121. });
  122. //# sourceMappingURL=advance.js.map