itemAlign.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import { each } from '@antv/util';
  2. import { vec2 } from '@antv/matrix-util';
  3. export default function(G6){
  4. const {mix} = G6.Util;
  5. G6.registerBehavior('itemAlign', {
  6. getDefaultCfg() {
  7. return {
  8. alignLineStyle: { stroke: '#FA8C16', lineWidth: 1 },
  9. tolerance: 5,
  10. _alignLines: [],
  11. };
  12. },
  13. getEvents() {
  14. return {
  15. 'afternodedrag': 'onDrag',
  16. 'afternodedragend': 'onDragEnd',
  17. };
  18. },
  19. onDrag(shape) {
  20. this._clearAlignLine();
  21. this._itemAlign(shape);
  22. },
  23. onDragEnd() {
  24. this._clearAlignLine();
  25. },
  26. _itemAlign(item){
  27. const bbox = item.getBBox();
  28. const ct = { x: bbox.x + bbox.width / 2, y: bbox.y };
  29. const cc = { x: bbox.x + bbox.width / 2, y: bbox.y + bbox.height / 2 };
  30. const cb = { x: bbox.x + bbox.width / 2, y: bbox.y + bbox.height };
  31. const lc = { x: bbox.x, y: bbox.y + bbox.height / 2 };
  32. const rc = { x: bbox.x + bbox.width, y: bbox.y + bbox.height / 2 };
  33. const nodes = this.graph.getNodes();
  34. each(nodes, (node) => {
  35. const horizontalLines = [];
  36. const verticalLines = [];
  37. let p = null;
  38. const bbox1 = node.getBBox();
  39. each(this.getHorizontalLines(bbox1), (line) => {
  40. horizontalLines.push(this.getDistance(line,ct));
  41. horizontalLines.push(this.getDistance(line,cc));
  42. horizontalLines.push(this.getDistance(line,cb));
  43. });
  44. each(this.getVerticalLines(bbox1), (line) => {
  45. verticalLines.push(this.getDistance(line,lc));
  46. verticalLines.push(this.getDistance(line,cc));
  47. verticalLines.push(this.getDistance(line,rc));
  48. });
  49. horizontalLines.sort((a,b)=> a.dis-b.dis);
  50. verticalLines.sort((a,b)=> a.dis-b.dis);
  51. if(horizontalLines.length > 0 && horizontalLines[0].dis < this.tolerance){
  52. item.attr({y: horizontalLines[0].line[1] - horizontalLines[0].point.y + bbox.y });
  53. p = { horizontals: [horizontalLines[0]] };
  54. for (let i = 1; i < 3; i++) horizontalLines[0].dis === horizontalLines[i].dis && p.horizontals.push(horizontalLines[i]);
  55. }
  56. if(verticalLines.length > 0 && verticalLines[0].dis < this.tolerance){
  57. item.attr({ x: verticalLines[0].line[0] - verticalLines[0].point.x + bbox.x });
  58. p ? p.verticals = [verticalLines[0]] : p = { verticals: [verticalLines[0]] };
  59. for (let i = 1; i < 3; i++) verticalLines[0].dis === verticalLines[i].dis && p.verticals.push(verticalLines[i]);
  60. }
  61. if(p){
  62. p.bbox = bbox;
  63. this._addAlignLine(p);
  64. }
  65. })
  66. },
  67. _addAlignLine(p){
  68. const group = this.graph.get('group');
  69. const bbox = p.bbox;
  70. const lineStyle = this.alignLineStyle;
  71. const lineArr = this._alignLines;
  72. if(p.horizontals){
  73. each(p.horizontals, function(lineObj) {
  74. const line = lineObj.line;
  75. const point = lineObj.point;
  76. const lineHalf = (line[0] + line[2]) / 2;
  77. let x1,x2;
  78. if(point.x < lineHalf){
  79. x1 = point.x - bbox.width / 2;
  80. x2 = Math.max(line[0], line[2]);
  81. }else{
  82. x1 = point.x + bbox.width / 2;
  83. x2 = Math.min(line[0], line[2]);
  84. }
  85. const shape = group.addShape('line', { attrs: mix({ x1, y1: line[1], x2, y2: line[1] }, lineStyle), capture: false });
  86. lineArr.push(shape);
  87. })
  88. }
  89. if(p.verticals){
  90. each(p.verticals, function(lineObj) {
  91. const line = lineObj.line;
  92. const point = lineObj.point;
  93. const lineHalf = (line[1] + line[3]) / 2;
  94. let y1,y2;
  95. if(point.y < lineHalf){
  96. y1 = point.y - bbox.height / 2;
  97. y2 = Math.max(line[1], line[3]);
  98. }else{
  99. y1 = point.y + bbox.height / 2;
  100. y2 = Math.min(line[1], line[3]);
  101. }
  102. const shape = group.addShape('line', { attrs: mix({ x1: line[0], y1, x2: line[0], y2 }, lineStyle), capture: false });
  103. lineArr.push(shape);
  104. })
  105. }
  106. },
  107. getHorizontalLines(bbox){
  108. return [
  109. [bbox.minX, bbox.minY, bbox.maxX, bbox.minY], // tltr
  110. [bbox.minX, bbox.centerY, bbox.maxX, bbox.centerY], // lcrc
  111. [bbox.minX, bbox.maxY, bbox.maxX, bbox.maxY], // blbr
  112. ]
  113. },
  114. getVerticalLines(bbox){
  115. return [
  116. [bbox.minX, bbox.minY, bbox.minX, bbox.maxY], // tlbl
  117. [bbox.centerX, bbox.minY, bbox.centerX, bbox.maxY], // tcbc
  118. [bbox.maxX, bbox.minY, bbox.maxX, bbox.maxY], // trbr
  119. ]
  120. },
  121. getDistance(line, point) {
  122. return { line, point, dis: this.pointLineDistance(line[0], line[1], line[2], line[3], point.x, point.y) };
  123. },
  124. pointLineDistance: function(lineX1, lineY1, lineX2, lineY2, pointX, pointY) {
  125. const lineLength = [lineX2 - lineX1, lineY2 - lineY1];
  126. if (vec2.exactEquals(lineLength, [0, 0])) return NaN;
  127. let s = [-lineLength[1], lineLength[0]];
  128. vec2.normalize(s, s);
  129. return Math.abs(vec2.dot([pointX - lineX1, pointY - lineY1], s));
  130. },
  131. _clearAlignLine(){
  132. each(this._alignLines, (line) => {
  133. line.remove();
  134. });
  135. this._alignLines = [];
  136. this.graph.paint();
  137. },
  138. });
  139. }