segments.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. "use strict";
  2. var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
  3. if (k2 === undefined) k2 = k;
  4. var desc = Object.getOwnPropertyDescriptor(m, k);
  5. if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
  6. desc = { enumerable: true, get: function() { return m[k]; } };
  7. }
  8. Object.defineProperty(o, k2, desc);
  9. }) : (function(o, m, k, k2) {
  10. if (k2 === undefined) k2 = k;
  11. o[k2] = m[k];
  12. }));
  13. var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
  14. Object.defineProperty(o, "default", { enumerable: true, value: v });
  15. }) : function(o, v) {
  16. o["default"] = v;
  17. });
  18. var __importStar = (this && this.__importStar) || function (mod) {
  19. if (mod && mod.__esModule) return mod;
  20. var result = {};
  21. if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
  22. __setModuleDefault(result, mod);
  23. return result;
  24. };
  25. Object.defineProperty(exports, "__esModule", { value: true });
  26. exports.Segments = void 0;
  27. const x6_common_1 = require("@antv/x6-common");
  28. const x6_geometry_1 = require("@antv/x6-geometry");
  29. const view_1 = require("../../view/view");
  30. const tool_1 = require("../../view/tool");
  31. const Util = __importStar(require("./util"));
  32. class Segments extends tool_1.ToolsView.ToolItem {
  33. constructor() {
  34. super(...arguments);
  35. this.handles = [];
  36. }
  37. get vertices() {
  38. return this.cellView.cell.getVertices();
  39. }
  40. update() {
  41. this.render();
  42. return this;
  43. }
  44. onRender() {
  45. x6_common_1.Dom.addClass(this.container, this.prefixClassName('edge-tool-segments'));
  46. this.resetHandles();
  47. const edgeView = this.cellView;
  48. const vertices = [...this.vertices];
  49. vertices.unshift(edgeView.sourcePoint);
  50. vertices.push(edgeView.targetPoint);
  51. for (let i = 0, l = vertices.length; i < l - 1; i += 1) {
  52. const vertex = vertices[i];
  53. const nextVertex = vertices[i + 1];
  54. const handle = this.renderHandle(vertex, nextVertex, i);
  55. this.stamp(handle.container);
  56. this.handles.push(handle);
  57. }
  58. return this;
  59. }
  60. renderHandle(vertex, nextVertex, index) {
  61. const handle = this.options.createHandle({
  62. index,
  63. graph: this.graph,
  64. guard: (evt) => this.guard(evt),
  65. attrs: this.options.attrs || {},
  66. });
  67. if (this.options.processHandle) {
  68. this.options.processHandle(handle);
  69. }
  70. this.updateHandle(handle, vertex, nextVertex);
  71. this.container.appendChild(handle.container);
  72. this.startHandleListening(handle);
  73. return handle;
  74. }
  75. startHandleListening(handle) {
  76. handle.on('change', this.onHandleChange, this);
  77. handle.on('changing', this.onHandleChanging, this);
  78. handle.on('changed', this.onHandleChanged, this);
  79. }
  80. stopHandleListening(handle) {
  81. handle.off('change', this.onHandleChange, this);
  82. handle.off('changing', this.onHandleChanging, this);
  83. handle.off('changed', this.onHandleChanged, this);
  84. }
  85. resetHandles() {
  86. const handles = this.handles;
  87. this.handles = [];
  88. if (handles) {
  89. handles.forEach((handle) => {
  90. this.stopHandleListening(handle);
  91. handle.remove();
  92. });
  93. }
  94. }
  95. shiftHandleIndexes(delta) {
  96. const handles = this.handles;
  97. for (let i = 0, n = handles.length; i < n; i += 1) {
  98. handles[i].options.index += delta;
  99. }
  100. }
  101. resetAnchor(type, anchor) {
  102. const edge = this.cellView.cell;
  103. const options = {
  104. ui: true,
  105. toolId: this.cid,
  106. };
  107. if (anchor) {
  108. edge.prop([type, 'anchor'], anchor, options);
  109. }
  110. else {
  111. edge.removeProp([type, 'anchor'], options);
  112. }
  113. }
  114. snapHandle(handle, position, data) {
  115. const axis = handle.options.axis;
  116. const index = handle.options.index;
  117. const edgeView = this.cellView;
  118. const edge = edgeView.cell;
  119. const vertices = edge.getVertices();
  120. const prev = vertices[index - 2] || data.sourceAnchor;
  121. const next = vertices[index + 1] || data.targetAnchor;
  122. const snapRadius = this.options.snapRadius;
  123. if (Math.abs(position[axis] - prev[axis]) < snapRadius) {
  124. position[axis] = prev[axis];
  125. }
  126. else if (Math.abs(position[axis] - next[axis]) < snapRadius) {
  127. position[axis] = next[axis];
  128. }
  129. return position;
  130. }
  131. onHandleChanging({ handle, e, }) {
  132. const graph = this.graph;
  133. const options = this.options;
  134. const edgeView = this.cellView;
  135. const anchorFn = options.anchor;
  136. const axis = handle.options.axis;
  137. const index = handle.options.index - 1;
  138. const data = this.getEventData(e);
  139. const evt = this.normalizeEvent(e);
  140. const coords = graph.snapToGrid(evt.clientX, evt.clientY);
  141. const position = this.snapHandle(handle, coords.clone(), data);
  142. const vertices = x6_common_1.ObjectExt.cloneDeep(this.vertices);
  143. let vertex = vertices[index];
  144. let nextVertex = vertices[index + 1];
  145. // First Segment
  146. const sourceView = edgeView.sourceView;
  147. const sourceBBox = edgeView.sourceBBox;
  148. let changeSourceAnchor = false;
  149. let deleteSourceAnchor = false;
  150. if (!vertex) {
  151. vertex = edgeView.sourceAnchor.toJSON();
  152. vertex[axis] = position[axis];
  153. if (sourceBBox.containsPoint(vertex)) {
  154. changeSourceAnchor = true;
  155. }
  156. else {
  157. vertices.unshift(vertex);
  158. this.shiftHandleIndexes(1);
  159. deleteSourceAnchor = true;
  160. }
  161. }
  162. else if (index === 0) {
  163. if (sourceBBox.containsPoint(vertex)) {
  164. vertices.shift();
  165. this.shiftHandleIndexes(-1);
  166. changeSourceAnchor = true;
  167. }
  168. else {
  169. vertex[axis] = position[axis];
  170. deleteSourceAnchor = true;
  171. }
  172. }
  173. else {
  174. vertex[axis] = position[axis];
  175. }
  176. if (typeof anchorFn === 'function' && sourceView) {
  177. if (changeSourceAnchor) {
  178. const sourceAnchorPosition = data.sourceAnchor.clone();
  179. sourceAnchorPosition[axis] = position[axis];
  180. const sourceAnchor = x6_common_1.FunctionExt.call(anchorFn, edgeView, sourceAnchorPosition, sourceView, edgeView.sourceMagnet || sourceView.container, 'source', edgeView, this);
  181. this.resetAnchor('source', sourceAnchor);
  182. }
  183. if (deleteSourceAnchor) {
  184. this.resetAnchor('source', data.sourceAnchorDef);
  185. }
  186. }
  187. // Last segment
  188. const targetView = edgeView.targetView;
  189. const targetBBox = edgeView.targetBBox;
  190. let changeTargetAnchor = false;
  191. let deleteTargetAnchor = false;
  192. if (!nextVertex) {
  193. nextVertex = edgeView.targetAnchor.toJSON();
  194. nextVertex[axis] = position[axis];
  195. if (targetBBox.containsPoint(nextVertex)) {
  196. changeTargetAnchor = true;
  197. }
  198. else {
  199. vertices.push(nextVertex);
  200. deleteTargetAnchor = true;
  201. }
  202. }
  203. else if (index === vertices.length - 2) {
  204. if (targetBBox.containsPoint(nextVertex)) {
  205. vertices.pop();
  206. changeTargetAnchor = true;
  207. }
  208. else {
  209. nextVertex[axis] = position[axis];
  210. deleteTargetAnchor = true;
  211. }
  212. }
  213. else {
  214. nextVertex[axis] = position[axis];
  215. }
  216. if (typeof anchorFn === 'function' && targetView) {
  217. if (changeTargetAnchor) {
  218. const targetAnchorPosition = data.targetAnchor.clone();
  219. targetAnchorPosition[axis] = position[axis];
  220. const targetAnchor = x6_common_1.FunctionExt.call(anchorFn, edgeView, targetAnchorPosition, targetView, edgeView.targetMagnet || targetView.container, 'target', edgeView, this);
  221. this.resetAnchor('target', targetAnchor);
  222. }
  223. if (deleteTargetAnchor) {
  224. this.resetAnchor('target', data.targetAnchorDef);
  225. }
  226. }
  227. if (!x6_geometry_1.Point.equalPoints(vertices, this.vertices)) {
  228. this.cellView.cell.setVertices(vertices, { ui: true, toolId: this.cid });
  229. }
  230. this.updateHandle(handle, vertex, nextVertex, 0);
  231. if (!options.stopPropagation) {
  232. edgeView.notifyMouseMove(evt, coords.x, coords.y);
  233. }
  234. }
  235. onHandleChange({ handle, e }) {
  236. const options = this.options;
  237. const handles = this.handles;
  238. const edgeView = this.cellView;
  239. const index = handle.options.index;
  240. if (!Array.isArray(handles)) {
  241. return;
  242. }
  243. for (let i = 0, n = handles.length; i < n; i += 1) {
  244. if (i !== index) {
  245. handles[i].hide();
  246. }
  247. }
  248. this.focus();
  249. this.setEventData(e, {
  250. sourceAnchor: edgeView.sourceAnchor.clone(),
  251. targetAnchor: edgeView.targetAnchor.clone(),
  252. sourceAnchorDef: x6_common_1.ObjectExt.cloneDeep(this.cell.prop(['source', 'anchor'])),
  253. targetAnchorDef: x6_common_1.ObjectExt.cloneDeep(this.cell.prop(['target', 'anchor'])),
  254. });
  255. this.cell.startBatch('move-segment', { ui: true, toolId: this.cid });
  256. if (!options.stopPropagation) {
  257. const normalizedEvent = this.normalizeEvent(e);
  258. const coords = this.graph.snapToGrid(normalizedEvent.clientX, normalizedEvent.clientY);
  259. edgeView.notifyMouseDown(normalizedEvent, coords.x, coords.y);
  260. }
  261. }
  262. onHandleChanged({ e }) {
  263. const options = this.options;
  264. const edgeView = this.cellView;
  265. if (options.removeRedundancies) {
  266. edgeView.removeRedundantLinearVertices({ ui: true, toolId: this.cid });
  267. }
  268. const normalizedEvent = this.normalizeEvent(e);
  269. const coords = this.graph.snapToGrid(normalizedEvent.clientX, normalizedEvent.clientY);
  270. this.render();
  271. this.blur();
  272. this.cell.stopBatch('move-segment', { ui: true, toolId: this.cid });
  273. if (!options.stopPropagation) {
  274. edgeView.notifyMouseUp(normalizedEvent, coords.x, coords.y);
  275. }
  276. edgeView.checkMouseleave(normalizedEvent);
  277. options.onChanged && options.onChanged({ edge: edgeView.cell, edgeView });
  278. }
  279. updateHandle(handle, vertex, nextVertex, offset = 0) {
  280. const precision = this.options.precision || 0;
  281. const vertical = Math.abs(vertex.x - nextVertex.x) < precision;
  282. const horizontal = Math.abs(vertex.y - nextVertex.y) < precision;
  283. if (vertical || horizontal) {
  284. const segmentLine = new x6_geometry_1.Line(vertex, nextVertex);
  285. const length = segmentLine.length();
  286. if (length < this.options.threshold) {
  287. handle.hide();
  288. }
  289. else {
  290. const position = segmentLine.getCenter();
  291. const axis = vertical ? 'x' : 'y';
  292. position[axis] += offset || 0;
  293. const angle = segmentLine.vector().vectorAngle(new x6_geometry_1.Point(1, 0));
  294. handle.updatePosition(position.x, position.y, angle, this.cellView);
  295. handle.show();
  296. handle.options.axis = axis;
  297. }
  298. }
  299. else {
  300. handle.hide();
  301. }
  302. }
  303. onRemove() {
  304. this.resetHandles();
  305. }
  306. }
  307. exports.Segments = Segments;
  308. (function (Segments) {
  309. class Handle extends view_1.View {
  310. constructor(options) {
  311. super();
  312. this.options = options;
  313. this.render();
  314. this.delegateEvents({
  315. mousedown: 'onMouseDown',
  316. touchstart: 'onMouseDown',
  317. });
  318. }
  319. render() {
  320. this.container = view_1.View.createElement('rect', true);
  321. const attrs = this.options.attrs;
  322. if (typeof attrs === 'function') {
  323. const defaults = Segments.getDefaults();
  324. this.setAttrs(Object.assign(Object.assign({}, defaults.attrs), attrs(this)));
  325. }
  326. else {
  327. this.setAttrs(attrs);
  328. }
  329. this.addClass(this.prefixClassName('edge-tool-segment'));
  330. }
  331. updatePosition(x, y, angle, view) {
  332. const p = view.getClosestPoint(new x6_geometry_1.Point(x, y)) || new x6_geometry_1.Point(x, y);
  333. let matrix = x6_common_1.Dom.createSVGMatrix().translate(p.x, p.y);
  334. if (!p.equals({ x, y })) {
  335. const line = new x6_geometry_1.Line(x, y, p.x, p.y);
  336. let deg = line.vector().vectorAngle(new x6_geometry_1.Point(1, 0));
  337. if (deg !== 0) {
  338. deg += 90;
  339. }
  340. matrix = matrix.rotate(deg);
  341. }
  342. else {
  343. matrix = matrix.rotate(angle);
  344. }
  345. this.setAttrs({
  346. transform: x6_common_1.Dom.matrixToTransformString(matrix),
  347. cursor: angle % 180 === 0 ? 'row-resize' : 'col-resize',
  348. });
  349. }
  350. onMouseDown(evt) {
  351. if (this.options.guard(evt)) {
  352. return;
  353. }
  354. this.trigger('change', { e: evt, handle: this });
  355. evt.stopPropagation();
  356. evt.preventDefault();
  357. this.options.graph.view.undelegateEvents();
  358. this.delegateDocumentEvents({
  359. mousemove: 'onMouseMove',
  360. touchmove: 'onMouseMove',
  361. mouseup: 'onMouseUp',
  362. touchend: 'onMouseUp',
  363. touchcancel: 'onMouseUp',
  364. }, evt.data);
  365. }
  366. onMouseMove(evt) {
  367. this.emit('changing', { e: evt, handle: this });
  368. }
  369. onMouseUp(evt) {
  370. this.emit('changed', { e: evt, handle: this });
  371. this.undelegateDocumentEvents();
  372. this.options.graph.view.delegateEvents();
  373. }
  374. show() {
  375. this.container.style.display = '';
  376. }
  377. hide() {
  378. this.container.style.display = 'none';
  379. }
  380. }
  381. Segments.Handle = Handle;
  382. })(Segments = exports.Segments || (exports.Segments = {}));
  383. (function (Segments) {
  384. Segments.config({
  385. name: 'segments',
  386. precision: 0.5,
  387. threshold: 40,
  388. snapRadius: 10,
  389. stopPropagation: true,
  390. removeRedundancies: true,
  391. attrs: {
  392. width: 20,
  393. height: 8,
  394. x: -10,
  395. y: -4,
  396. rx: 4,
  397. ry: 4,
  398. fill: '#333',
  399. stroke: '#fff',
  400. 'stroke-width': 2,
  401. },
  402. createHandle: (options) => new Segments.Handle(options),
  403. anchor: Util.getAnchor,
  404. });
  405. })(Segments = exports.Segments || (exports.Segments = {}));
  406. //# sourceMappingURL=segments.js.map