edge.ts 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743
  1. import { StructureType, MindmapConnectorType, TopicType } from "@/enum";
  2. import { TopicItem } from "@/types";
  3. import { Edge, Graph, Path } from "@antv/x6";
  4. import { getTheme } from "./theme";
  5. import { caclculateX } from "@/utils/hierarchy/rightFishbone";
  6. // 曲线
  7. Graph.registerConnector(
  8. "curve-branch-connector",
  9. (sourcePoint, targetPoint, routerPoints, options) => {
  10. const midX = sourcePoint.x;
  11. const ctrX = (targetPoint.x - midX) / 5 + midX;
  12. const ctrY = targetPoint.y;
  13. const pathData = `
  14. M ${sourcePoint.x} ${sourcePoint.y}
  15. Q ${ctrX} ${ctrY} ${targetPoint.x} ${targetPoint.y}
  16. `;
  17. return options.raw ? Path.parse(pathData) : pathData;
  18. },
  19. true
  20. );
  21. Graph.registerConnector(
  22. "curve-sub-connector",
  23. (sourcePoint, targetPoint, routerPoints, options) => {
  24. const midX = sourcePoint.x + (sourcePoint.x < targetPoint.x ? 10 : -10);
  25. const midY = sourcePoint.y;
  26. const ctrX = (targetPoint.x - midX) / 5 + midX;
  27. const ctrY = targetPoint.y;
  28. const pathData = `
  29. M ${sourcePoint.x} ${sourcePoint.y}
  30. L ${midX} ${midY}
  31. Q ${ctrX} ${ctrY} ${targetPoint.x} ${targetPoint.y}
  32. `;
  33. return options.raw ? Path.parse(pathData) : pathData;
  34. },
  35. true
  36. );
  37. // 直线
  38. Graph.registerConnector(
  39. "straight-branch-connector",
  40. function (sourcePoint, targetPoint, routerPoints, options) {
  41. const halfWidth = this.sourceBBox.width / 2;
  42. const midX =
  43. sourcePoint.x +
  44. (sourcePoint.x < targetPoint.x ? halfWidth + 10 : -halfWidth - 10);
  45. const midY = sourcePoint.y;
  46. const pathData = `
  47. M ${sourcePoint.x} ${sourcePoint.y}
  48. L ${midX} ${midY}
  49. L ${targetPoint.x} ${targetPoint.y}
  50. `;
  51. return options.raw ? Path.parse(pathData) : pathData;
  52. },
  53. true
  54. );
  55. Graph.registerConnector(
  56. "straight-sub-connector",
  57. function (sourcePoint, targetPoint, routerPoints, options) {
  58. const midX = sourcePoint.x + (sourcePoint.x < targetPoint.x ? 10 : -10);
  59. const midY = sourcePoint.y;
  60. const pathData = `
  61. M ${sourcePoint.x} ${sourcePoint.y}
  62. L ${midX} ${midY}
  63. L ${targetPoint.x} ${targetPoint.y}
  64. `;
  65. return options.raw ? Path.parse(pathData) : pathData;
  66. },
  67. true
  68. );
  69. // 圆角折线
  70. Graph.registerConnector(
  71. "rounded-branch-connector",
  72. function (sourcePoint, targetPoint, routerPoints, options) {
  73. const halfWidth = this.sourceBBox.width / 2;
  74. const midX =
  75. sourcePoint.x +
  76. (sourcePoint.x < targetPoint.x ? halfWidth + 10 : -halfWidth - 10);
  77. const midY = sourcePoint.y;
  78. const pathData = `
  79. M ${sourcePoint.x} ${sourcePoint.y}
  80. L ${midX} ${midY}
  81. L ${midX} ${targetPoint.y + (targetPoint.y < sourcePoint.y ? 5 : targetPoint.y === sourcePoint.y ? 0 : -5)}
  82. Q ${midX} ${targetPoint.y} ${midX + (targetPoint.x < sourcePoint.x ? -5 : 5)} ${targetPoint.y}
  83. L ${targetPoint.x} ${targetPoint.y}
  84. `;
  85. return options.raw ? Path.parse(pathData) : pathData;
  86. },
  87. true
  88. );
  89. Graph.registerConnector(
  90. "rounded-sub-connector",
  91. (sourcePoint, targetPoint, routerPoints, options) => {
  92. const midX =
  93. sourcePoint.x < targetPoint.x ? sourcePoint.x + 10 : sourcePoint.x - 10;
  94. const midY = sourcePoint.y;
  95. // 可能存在误差
  96. const deviationY = Math.abs(targetPoint.y - sourcePoint.y);
  97. const pathData =
  98. deviationY < 10
  99. ? `M ${sourcePoint.x} ${sourcePoint.y}
  100. L ${targetPoint.x} ${targetPoint.y}
  101. `
  102. : `
  103. M ${sourcePoint.x} ${sourcePoint.y}
  104. L ${midX} ${midY}
  105. L ${midX} ${targetPoint.y + (targetPoint.y < sourcePoint.y ? 5 : -5)}
  106. Q ${midX} ${targetPoint.y} ${midX + (targetPoint.x < sourcePoint.x ? -5 : 5)} ${targetPoint.y}
  107. L ${targetPoint.x} ${targetPoint.y}
  108. `;
  109. return options.raw ? Path.parse(pathData) : pathData;
  110. },
  111. true
  112. );
  113. // 折线
  114. Graph.registerConnector(
  115. "poly-branch-connector",
  116. function (sourcePoint, targetPoint, routerPoints, options) {
  117. const halfWidth = this.sourceBBox.width / 2;
  118. const midX =
  119. sourcePoint.x +
  120. (sourcePoint.x < targetPoint.x ? halfWidth + 10 : -halfWidth - 10);
  121. const midY = sourcePoint.y;
  122. const pathData = `
  123. M ${sourcePoint.x} ${sourcePoint.y}
  124. L ${midX} ${midY}
  125. L ${midX} ${targetPoint.y}
  126. L ${targetPoint.x} ${targetPoint.y}
  127. `;
  128. return options.raw ? Path.parse(pathData) : pathData;
  129. },
  130. true
  131. );
  132. Graph.registerConnector(
  133. "poly-sub-connector",
  134. function (sourcePoint, targetPoint, routerPoints, options) {
  135. const midX = sourcePoint.x + (sourcePoint.x < targetPoint.x ? 10 : -10);
  136. const midY = sourcePoint.y;
  137. const pathData = `
  138. M ${sourcePoint.x} ${sourcePoint.y}
  139. L ${midX} ${midY}
  140. L ${midX} ${targetPoint.y}
  141. L ${targetPoint.x} ${targetPoint.y}
  142. `;
  143. return options.raw ? Path.parse(pathData) : pathData;
  144. },
  145. true
  146. );
  147. // 树形
  148. Graph.registerConnector(
  149. "tree-branch-connector",
  150. function (sourcePoint, targetPoint, routerPoints, options) {
  151. const pathData = `
  152. M ${sourcePoint.x} ${sourcePoint.y}
  153. L ${sourcePoint.x} ${sourcePoint.y + 10}
  154. L ${targetPoint.x} ${sourcePoint.y + 10}
  155. L ${targetPoint.x} ${targetPoint.y}
  156. `;
  157. return options.raw ? Path.parse(pathData) : pathData;
  158. },
  159. true
  160. );
  161. Graph.registerConnector(
  162. "tree-sub-connector",
  163. function (sourcePoint, targetPoint, routerPoints, options) {
  164. const pathData = `
  165. M ${sourcePoint.x} ${sourcePoint.y}
  166. L ${sourcePoint.x} ${targetPoint.y}
  167. L ${targetPoint.x} ${targetPoint.y}
  168. `;
  169. return options.raw ? Path.parse(pathData) : pathData;
  170. },
  171. true
  172. );
  173. // 组织结构
  174. Graph.registerConnector(
  175. "organization-branch-connector",
  176. function (sourcePoint, targetPoint, routerPoints, options) {
  177. const pathData = `
  178. M ${sourcePoint.x} ${sourcePoint.y}
  179. L ${sourcePoint.x} ${sourcePoint.y + 10}
  180. L ${targetPoint.x} ${sourcePoint.y + 10}
  181. L ${targetPoint.x} ${targetPoint.y}
  182. `;
  183. return options.raw ? Path.parse(pathData) : pathData;
  184. },
  185. true
  186. );
  187. Graph.registerConnector(
  188. "organization-sub-connector",
  189. function (sourcePoint, targetPoint, routerPoints, options) {
  190. const pathData = `
  191. M ${sourcePoint.x} ${sourcePoint.y}
  192. L ${sourcePoint.x} ${sourcePoint.y + 10}
  193. L ${targetPoint.x} ${sourcePoint.y + 10}
  194. L ${targetPoint.x} ${targetPoint.y}
  195. `;
  196. return options.raw ? Path.parse(pathData) : pathData;
  197. },
  198. true
  199. );
  200. // 括号
  201. Graph.registerConnector(
  202. "bracket-branch-connector",
  203. function (sourcePoint, targetPoint, routerPoints, options) {
  204. const midX = sourcePoint.x + (sourcePoint.x < targetPoint.x ? 20 : -20);
  205. const midY = sourcePoint.y;
  206. const pathData = `
  207. M ${sourcePoint.x} ${sourcePoint.y}
  208. Q ${midX} ${midY} ${midX} ${sourcePoint.y + (sourcePoint.y < targetPoint.y ? 20 : -20)}
  209. L ${midX} ${targetPoint.y + (targetPoint.y < sourcePoint.y ? 20 : targetPoint.y === sourcePoint.y ? 0 : -20)}
  210. Q ${midX} ${targetPoint.y} ${midX + (targetPoint.x < sourcePoint.x ? -20 : 20)} ${targetPoint.y}
  211. `;
  212. return options.raw ? Path.parse(pathData) : pathData;
  213. },
  214. true
  215. );
  216. Graph.registerConnector(
  217. "bracket-sub-connector",
  218. function (sourcePoint, targetPoint, routerPoints, options) {
  219. const midX = sourcePoint.x + (sourcePoint.x < targetPoint.x ? 10 : -10);
  220. const midY = sourcePoint.y;
  221. const pathData = `
  222. M ${sourcePoint.x} ${sourcePoint.y}
  223. Q ${midX} ${midY} ${midX} ${sourcePoint.y + (sourcePoint.y < targetPoint.y ? 10 : -10)}
  224. L ${midX} ${targetPoint.y + (targetPoint.y < sourcePoint.y ? 10 : targetPoint.y === sourcePoint.y ? 0 : -10)}
  225. Q ${midX} ${targetPoint.y} ${midX + (targetPoint.x < sourcePoint.x ? -10 : 10)} ${targetPoint.y}
  226. `;
  227. return options.raw ? Path.parse(pathData) : pathData;
  228. },
  229. true
  230. );
  231. // 一个子项的括号
  232. Graph.registerConnector(
  233. "bracket-one-branch-connector",
  234. function (sourcePoint, targetPoint, routerPoints, options, edgeView) {
  235. const targetCell = edgeView.targetView?.cell;
  236. let height = 0;
  237. if (targetCell?.isNode()) {
  238. height = targetCell.getBBox().height;
  239. }
  240. const targetTop = targetPoint.y - height / 2 - 3;
  241. const targetBottom = targetPoint.y + height / 2 + 3;
  242. const offset = 10;
  243. const midX =
  244. sourcePoint.x + (sourcePoint.x < targetPoint.x ? offset : -offset);
  245. const midY = sourcePoint.y;
  246. const pathData = `
  247. M ${sourcePoint.x} ${sourcePoint.y}
  248. Q ${midX} ${midY} ${midX} ${sourcePoint.y - offset}
  249. L ${midX} ${targetTop + offset}
  250. Q ${midX} ${targetTop} ${midX + offset} ${targetTop}
  251. M ${sourcePoint.x} ${sourcePoint.y}
  252. Q ${midX} ${midY} ${midX} ${sourcePoint.y + offset}
  253. L ${midX} ${targetBottom - offset}
  254. Q ${midX} ${targetBottom} ${midX + offset} ${targetBottom}
  255. `;
  256. return options.raw ? Path.parse(pathData) : pathData;
  257. },
  258. true
  259. );
  260. Graph.registerConnector(
  261. "bracket-one-sub-connector",
  262. function (sourcePoint, targetPoint, routerPoints, options, edgeView) {
  263. const targetCell = edgeView.targetView?.cell;
  264. let height = 0;
  265. if (targetCell?.isNode()) {
  266. height = targetCell.getBBox().height;
  267. }
  268. const targetTop = targetPoint.y - height / 2 + 3;
  269. const targetBottom = targetPoint.y + height / 2 - 3;
  270. const offset = 5;
  271. const midX =
  272. sourcePoint.x + (sourcePoint.x < targetPoint.x ? offset : -offset);
  273. const midY = sourcePoint.y;
  274. const pathData = `
  275. M ${sourcePoint.x} ${sourcePoint.y}
  276. Q ${midX} ${midY} ${midX} ${sourcePoint.y - offset}
  277. L ${midX} ${targetTop + offset}
  278. Q ${midX} ${targetTop} ${midX + offset} ${targetTop}
  279. M ${sourcePoint.x} ${sourcePoint.y}
  280. Q ${midX} ${midY} ${midX} ${sourcePoint.y + offset}
  281. L ${midX} ${targetBottom - offset}
  282. Q ${midX} ${targetBottom} ${midX + offset} ${targetBottom}
  283. `;
  284. return options.raw ? Path.parse(pathData) : pathData;
  285. },
  286. true
  287. );
  288. // 树形图
  289. Graph.registerConnector(
  290. "tree-shape-connector",
  291. function (sourcePoint, targetPoint, routerPoints, options) {
  292. const pathData = `
  293. M ${sourcePoint.x} ${sourcePoint.y}
  294. L ${sourcePoint.x} ${targetPoint.y}
  295. L ${targetPoint.x} ${targetPoint.y}
  296. `;
  297. return options.raw ? Path.parse(pathData) : pathData;
  298. },
  299. true
  300. );
  301. // 右侧鱼骨图
  302. Graph.registerConnector(
  303. "fishbone-branch-right-connector",
  304. function (sourcePoint, targetPoint, routerPoints, options, edgeView) {
  305. const direction = sourcePoint.y > targetPoint.y ? "up" : "down";
  306. const node = edgeView.targetView?.cell;
  307. let targetY = targetPoint.y;
  308. if (node?.isNode() && direction === "down") {
  309. targetY -= node.size().height;
  310. }
  311. const midX = caclculateX(
  312. { x: targetPoint.x, y: targetY },
  313. sourcePoint.y,
  314. "right",
  315. direction
  316. );
  317. let pathData = "";
  318. if (direction === "up") {
  319. pathData = `
  320. M ${targetPoint.x} ${targetPoint.y}
  321. L ${midX} ${sourcePoint.y}
  322. L ${sourcePoint.x} ${sourcePoint.y}
  323. `;
  324. } else {
  325. pathData = `
  326. M ${targetPoint.x} ${targetY}
  327. L ${midX} ${sourcePoint.y}
  328. L ${sourcePoint.x} ${sourcePoint.y}
  329. `;
  330. }
  331. return options.raw ? Path.parse(pathData) : pathData;
  332. },
  333. true
  334. );
  335. Graph.registerConnector(
  336. "fishbone-sub-right-connector",
  337. function (sourcePoint, targetPoint, routerPoints, options, edgeView) {
  338. const sourceNode = edgeView.sourceView?.cell;
  339. const direction = sourcePoint.y < targetPoint.y ? "up" : "down";
  340. let midX = caclculateX(sourcePoint, targetPoint.y, "right", direction);
  341. if (direction === "down" && sourceNode?.isNode()) {
  342. midX = caclculateX(
  343. { x: sourcePoint.x, y: sourcePoint.y - sourceNode.size().height },
  344. targetPoint.y,
  345. "right",
  346. direction
  347. );
  348. }
  349. let pathData = "";
  350. if (sourceNode?.isNode() && sourceNode.data.type === TopicType.sub) {
  351. const size = sourceNode.size();
  352. const sourceP = {
  353. x: sourcePoint.x + size.width / 2,
  354. y: sourcePoint.y - size.height / 2,
  355. };
  356. pathData = `
  357. M ${sourceP.x} ${sourceP.y}
  358. L ${sourceP.x + 10} ${sourceP.y}
  359. L ${sourceP.x + 10} ${targetPoint.y}
  360. L ${targetPoint.x} ${targetPoint.y}
  361. `;
  362. } else {
  363. pathData = `
  364. M ${midX} ${targetPoint.y}
  365. L ${targetPoint.x} ${targetPoint.y}
  366. `;
  367. }
  368. return options.raw ? Path.parse(pathData) : pathData;
  369. },
  370. true
  371. );
  372. // 左侧鱼骨图
  373. Graph.registerConnector(
  374. "fishbone-branch-left-connector",
  375. function (sourcePoint, targetPoint, routerPoints, options, edgeView) {
  376. const direction = sourcePoint.y > targetPoint.y ? "up" : "down";
  377. const node = edgeView.targetView?.cell;
  378. let targetY = targetPoint.y;
  379. if (node?.isNode() && direction === "down") {
  380. targetY -= node.size().height;
  381. }
  382. const midX = caclculateX(
  383. { x: targetPoint.x, y: targetY },
  384. sourcePoint.y,
  385. "left",
  386. direction
  387. );
  388. let pathData = "";
  389. if (direction === "up") {
  390. pathData = `
  391. M ${targetPoint.x} ${targetPoint.y}
  392. L ${midX} ${sourcePoint.y}
  393. L ${sourcePoint.x} ${sourcePoint.y}
  394. `;
  395. } else {
  396. pathData = `
  397. M ${targetPoint.x} ${targetY}
  398. L ${midX} ${sourcePoint.y}
  399. L ${sourcePoint.x} ${sourcePoint.y}
  400. `;
  401. }
  402. return options.raw ? Path.parse(pathData) : pathData;
  403. },
  404. true
  405. );
  406. Graph.registerConnector(
  407. "fishbone-sub-left-connector",
  408. function (sourcePoint, targetPoint, routerPoints, options, edgeView) {
  409. const sourceNode = edgeView.sourceView?.cell;
  410. let pathData = "";
  411. // 子主题到子主题
  412. if (sourceNode?.isNode() && sourceNode.data.type === TopicType.sub) {
  413. const size = sourceNode.size();
  414. const sourceP = {
  415. x: sourcePoint.x - size.width,
  416. y: sourcePoint.y,
  417. };
  418. pathData = `
  419. M ${sourceP.x} ${sourceP.y}
  420. L ${sourceP.x - 10} ${sourceP.y}
  421. L ${sourceP.x - 10} ${targetPoint.y}
  422. L ${targetPoint.x} ${targetPoint.y}
  423. `;
  424. } else {
  425. // 分支子主题到子主题
  426. const direction = sourcePoint.y < targetPoint.y ? "up" : "down";
  427. const size = sourceNode?.isNode()
  428. ? sourceNode.size()
  429. : { width: 0, height: 0 };
  430. let midX = caclculateX(
  431. {
  432. x: sourcePoint.x - size.width / 2,
  433. y: sourcePoint.y + size.height / 2,
  434. },
  435. targetPoint.y,
  436. "left",
  437. direction
  438. );
  439. if (direction === "down") {
  440. midX = caclculateX(
  441. {
  442. x: sourcePoint.x - size.width / 2,
  443. y: sourcePoint.y - size.height / 2,
  444. },
  445. targetPoint.y,
  446. "left",
  447. direction
  448. );
  449. }
  450. pathData = `
  451. M ${midX} ${targetPoint.y}
  452. L ${targetPoint.x} ${targetPoint.y}
  453. `;
  454. }
  455. return options.raw ? Path.parse(pathData) : pathData;
  456. },
  457. true
  458. );
  459. const getConnector = (
  460. structure: StructureType,
  461. theme: string,
  462. type: TopicType,
  463. options?: Record<string, any>
  464. ) => {
  465. // 树状结构图
  466. if (structure === StructureType.tree) {
  467. return `tree-${type}-connector`;
  468. }
  469. // 组织结构图
  470. if (structure === StructureType.organization) {
  471. return `organization-${type}-connector`;
  472. }
  473. // 时间图
  474. if (
  475. [
  476. StructureType.upwardTime,
  477. StructureType.downwardTime,
  478. StructureType.horizontalTime,
  479. ].includes(structure)
  480. ) {
  481. return `poly-${type}-connector`;
  482. }
  483. // 括号图
  484. if (
  485. [StructureType.leftBracket, StructureType.rightBracket].includes(structure)
  486. ) {
  487. if (options?.onlyOneChild) {
  488. return `bracket-one-${type}-connector`;
  489. }
  490. return `bracket-${type}-connector`;
  491. }
  492. // 树形图
  493. if (
  494. [
  495. StructureType.leftTreeShape,
  496. StructureType.rightTreeShape,
  497. StructureType.treeShape,
  498. ].includes(structure)
  499. ) {
  500. return `tree-shape-connector`;
  501. }
  502. // 鱼骨
  503. if (structure === StructureType.leftFishbone) {
  504. return `fishbone-${type}-left-connector`;
  505. }
  506. if (structure === StructureType.rightFishbone) {
  507. return `fishbone-${type}-right-connector`;
  508. }
  509. const themeObj = getTheme(theme);
  510. if (type === TopicType.branch) {
  511. return `${themeObj.branchConnector}-${type}-connector`;
  512. } else {
  513. return `${themeObj.subConnector}-${type}-connector`;
  514. }
  515. };
  516. const getSourceAnchor = (
  517. type: TopicType,
  518. structure: StructureType,
  519. options?: Record<string, any>
  520. ) => {
  521. switch (structure) {
  522. case StructureType.left: {
  523. return type === TopicType.branch
  524. ? {
  525. name: "center",
  526. }
  527. : {
  528. name: "left",
  529. };
  530. }
  531. case StructureType.right: {
  532. return type === TopicType.branch
  533. ? {
  534. name: "center",
  535. }
  536. : {
  537. name: "right",
  538. };
  539. }
  540. case StructureType.leftRight: {
  541. return type === TopicType.branch
  542. ? "center"
  543. : options?.direction === "left"
  544. ? "left"
  545. : "right";
  546. }
  547. case StructureType.tree: {
  548. return type === TopicType.branch
  549. ? {
  550. name: "bottom",
  551. args: {
  552. dy: -5,
  553. },
  554. }
  555. : {
  556. name: "bottomLeft",
  557. args: {
  558. dx: 10,
  559. },
  560. };
  561. }
  562. case StructureType.organization: {
  563. return {
  564. name: "bottom",
  565. };
  566. }
  567. case StructureType.leftBracket: {
  568. return {
  569. name: "left",
  570. args: {
  571. dx: -10,
  572. },
  573. };
  574. }
  575. case StructureType.rightBracket: {
  576. return {
  577. name: "right",
  578. args: {
  579. dx: 10,
  580. },
  581. };
  582. }
  583. case StructureType.upwardTime:
  584. case StructureType.downwardTime:
  585. case StructureType.horizontalTime: {
  586. return {
  587. name: "center",
  588. };
  589. }
  590. case StructureType.leftFishbone: {
  591. return {
  592. name: type === TopicType.branch ? "left" : "right",
  593. };
  594. }
  595. case StructureType.rightFishbone:
  596. return {
  597. name: type === TopicType.branch ? "right" : "bottom",
  598. };
  599. case StructureType.leftTreeShape:
  600. case StructureType.rightTreeShape:
  601. case StructureType.treeShape: {
  602. return "bottom";
  603. }
  604. }
  605. return {
  606. name: "center",
  607. };
  608. };
  609. const getTargetAnchor = (
  610. type: TopicType,
  611. structure: StructureType,
  612. options?: Record<string, any>
  613. ) => {
  614. switch (structure) {
  615. case StructureType.left: {
  616. return {
  617. name: "right",
  618. };
  619. }
  620. case StructureType.right: {
  621. return {
  622. name: "left",
  623. };
  624. }
  625. case StructureType.leftRight: {
  626. return options?.direction === "left" ? "right" : "left";
  627. }
  628. case StructureType.tree: {
  629. return type === TopicType.branch
  630. ? {
  631. name: "top",
  632. }
  633. : {
  634. name: "left",
  635. };
  636. }
  637. case StructureType.organization: {
  638. return {
  639. name: "top",
  640. };
  641. }
  642. case StructureType.leftBracket: {
  643. return {
  644. name: "right",
  645. args: {
  646. dx: 10,
  647. },
  648. };
  649. }
  650. case StructureType.rightBracket: {
  651. return {
  652. name: "left",
  653. args: {
  654. dx: 10,
  655. },
  656. };
  657. }
  658. case StructureType.upwardTime:
  659. case StructureType.downwardTime:
  660. case StructureType.horizontalTime: {
  661. return {
  662. name: "left",
  663. };
  664. }
  665. case StructureType.leftFishbone: {
  666. return {
  667. name: type === TopicType.branch ? "bottom" : "right",
  668. };
  669. }
  670. case StructureType.rightFishbone:
  671. return {
  672. name: type === TopicType.branch ? "bottom" : "left",
  673. };
  674. case StructureType.leftTreeShape:
  675. case StructureType.rightTreeShape:
  676. case StructureType.treeShape: {
  677. return "left";
  678. }
  679. }
  680. return {
  681. name: "center",
  682. args: {
  683. dx: "25%",
  684. },
  685. };
  686. };
  687. /**
  688. * 创建连线
  689. * @param graph
  690. * @param sourceId
  691. * @param item
  692. * @param structure
  693. * @param theme
  694. * @returns
  695. */
  696. export const createEdge = (
  697. graph: Graph,
  698. sourceId: string,
  699. item: { id: string; data: TopicItem },
  700. structure: StructureType,
  701. theme: string,
  702. options: Record<string, any> = {}
  703. ): Edge => {
  704. return graph.createEdge({
  705. id: item.id + "-edge",
  706. inherit: "edge",
  707. connector: {
  708. name: getConnector(structure, theme, item.data.type, options),
  709. },
  710. zIndex: 0,
  711. source: {
  712. cell: sourceId,
  713. anchor: getSourceAnchor(item.data.type, structure, options),
  714. },
  715. target: {
  716. cell: item.id,
  717. anchor: getTargetAnchor(item.data.type, structure, options),
  718. },
  719. attrs: {
  720. line: {
  721. targetMarker: "",
  722. stroke: item.data.edge?.color || "#A2B1C3",
  723. strokeWidth: item.data?.edge?.width || 3,
  724. },
  725. },
  726. });
  727. };