@mx-sose-front/mx-sose-graph 1.1.8 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/edgeWorker-b57ca007.js +2 -0
- package/dist/assets/edgeWorker-b57ca007.js.map +1 -0
- package/dist/index.d.ts +994 -31
- package/dist/index.esm.js +9541 -5145
- package/dist/index.esm.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/Common/Tree.vue +451 -0
- package/src/components/Common/index.ts +2 -0
- package/src/components/DiagramListTooltip/DiagramListTooltip.vue +1 -2
- package/src/components/Edge/Edge.vue +172 -169
- package/src/components/Gantt/Gantt.vue +1544 -0
- package/src/components/GanttContextMenu/GanttContextMenu.vue +304 -0
- package/src/components/InteractionLayer.vue +343 -147
- package/src/components/Matrix/Matrix.vue +808 -0
- package/src/components/Matrix/index.ts +168 -0
- package/src/components/Shape/ConceptualRole.vue +2 -34
- package/src/components/Table/Table.vue +1193 -0
- package/src/constants/edgeShapeKeys.ts +8 -5
- package/src/constants/index.ts +279 -51
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useChartRowSelection.ts +456 -0
- package/src/hooks/useResize.ts +2 -2
- package/src/hooks/useVirtualScroll.ts +258 -0
- package/src/index.ts +1 -1
- package/src/render/shape-renderer.ts +62 -2
- package/src/statics/icons/childIcons/AV-1/346/246/202/350/277/260/344/270/216/346/221/230/350/246/201/344/277/241/346/201/257/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/AV-1/346/246/202/350/277/260/346/221/230/350/246/201/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/AV-2/351/233/206/346/210/220/345/255/227/345/205/270/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/AV-2/351/233/206/346/210/220/345/255/227/345/205/270/350/241/250@3x.png +0 -0
- package/src/statics/icons/childIcons/CV-1/346/204/277/346/231/257/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/CV-1/346/204/277/346/231/257/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/CV-2/350/203/275/345/212/233/345/210/206/347/261/273/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/CV-2/350/203/275/345/212/233/345/210/206/347/261/273/345/233/276@3x-2.png +0 -0
- package/src/statics/icons/childIcons/CV-2/350/203/275/345/212/233/345/210/206/347/261/273/345/233/276@3x-3.png +0 -0
- package/src/statics/icons/childIcons/CV-2/350/203/275/345/212/233/345/210/206/347/261/273/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/CV-3/350/203/275/345/212/233/345/210/206/346/256/265/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/CV-3/350/203/275/345/212/233/351/230/266/346/256/265/347/224/230/347/211/271/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/CV-4/350/203/275/345/212/233/344/276/235/350/265/226/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/CV-4/350/203/275/345/212/233/344/276/235/350/265/226/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/CV-5/350/203/275/345/212/233/345/210/260/347/273/204/347/273/207/347/232/204/345/274/200/345/217/221/346/230/240/345/260/204/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/CV-5/350/203/275/345/212/233/345/210/260/347/273/204/347/273/207/347/232/204/346/230/240/345/260/204/347/237/251/351/230/265@3x.png +0 -0
- package/src/statics/icons/childIcons/CV-6/350/203/275/345/212/233/345/210/260/344/270/232/345/212/241/346/264/273/345/212/250/346/230/240/345/260/204/347/237/251/351/230/265@3x.png +0 -0
- package/src/statics/icons/childIcons/CV-6/350/203/275/345/212/233/345/210/260/344/275/234/346/210/230/346/264/273/345/212/250/347/232/204/346/230/240/345/260/204/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/CV-7/350/203/275/345/212/233/345/210/260/346/234/215/345/212/241/346/230/240/345/260/204/347/237/251/351/230/265@3x.png +0 -0
- package/src/statics/icons/childIcons/CV-7/350/203/275/345/212/233/345/210/260/346/234/215/345/212/241/347/232/204/346/230/240/345/260/204/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/DIV-1/346/246/202/345/277/265/346/225/260/346/215/256/346/250/241/345/236/213/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/DIV-1/346/246/202/345/277/265/346/225/260/346/215/256/346/250/241/345/236/213/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/DIV-2/351/200/273/350/276/221/346/225/260/346/215/256/346/250/241/345/236/213/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/DIV-2/351/200/273/350/276/221/346/225/260/346/215/256/346/250/241/345/236/213/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/DIV-3/347/211/251/347/220/206/346/225/260/346/215/256/346/250/241/345/236/213/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/OV-1/350/207/252/347/224/261/345/210/206/347/261/273/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/OV-1/351/253/230/347/272/247/344/275/234/346/210/230/346/246/202/345/277/265/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/OV-1/351/253/230/347/272/247/344/275/234/346/210/230/346/246/202/345/277/265/345/233/276/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/OV-2/344/275/234/346/210/230/350/265/204/346/272/220/346/265/201/345/206/205/351/203/250/346/217/217/350/277/260/345/233/276@3x-2.png +0 -0
- package/src/statics/icons/childIcons/OV-2/344/275/234/346/210/230/350/265/204/346/272/220/346/265/201/345/206/205/351/203/250/346/217/217/350/277/260/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/OV-2/344/275/234/346/210/230/350/265/204/346/272/220/346/265/201/346/217/217/350/277/260/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/OV-2/344/275/234/346/210/230/350/265/204/346/272/220/346/265/201/346/217/217/350/277/260/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/OV-3/344/275/234/346/210/230/350/265/204/346/272/220/346/265/201/347/237/251/351/230/265@3x.png +0 -0
- package/src/statics/icons/childIcons/OV-3/344/275/234/346/210/230/350/265/204/346/272/220/346/265/201/347/237/251/351/230/265/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/OV-3/345/237/272/347/241/200/350/247/222/350/211/262/344/275/234/346/210/230/350/265/204/346/272/220/346/265/201/347/237/251/351/230/265@3x.png +0 -0
- package/src/statics/icons/childIcons/OV-4/347/273/204/347/273/207/345/205/263/347/263/273/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/OV-4/347/273/204/347/273/207/345/205/263/347/263/273/345/233/276/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/OV-5a/344/275/234/346/210/230/346/264/273/345/212/250/345/210/206/350/247/243/346/240/221/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/OV-5a/344/275/234/346/210/230/346/264/273/345/212/250/345/210/206/350/247/243/346/240/221/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/OV-5b/344/275/234/346/210/230/346/264/273/345/212/250/346/250/241/345/236/213/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/OV-5b/344/275/234/346/210/230/346/264/273/345/212/250/346/250/241/345/236/213/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/OV-6a/344/275/234/346/210/230/350/247/204/345/210/231/346/250/241/345/236/213/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/OV-6a/344/275/234/346/210/230/350/265/204/346/272/220/345/217/202/346/225/260/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/OV-6b/347/212/266/346/200/201/350/275/254/346/215/242/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/OV-6b/347/212/266/346/200/201/350/275/254/346/215/242/346/250/241/345/236/213/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/OV-6c/344/272/213/344/273/266/350/277/275/350/270/252/346/217/217/350/277/260/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/OV-6c/344/275/234/346/210/230/344/272/213/344/273/266/350/267/237/350/270/252/346/217/217/350/277/260/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/PV-1/351/241/271/347/233/256/347/273/204/345/220/210/345/205/263/347/263/273/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/PV-1/351/241/271/347/233/256/347/273/204/345/220/210/345/205/263/347/263/273/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/PV-2/351/241/271/347/233/256/346/227/266/351/227/264/350/277/233/345/272/246/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/PV-2/351/241/271/347/233/256/346/227/266/351/227/264/350/277/233/345/272/246/347/224/230/347/211/271/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/PV-3/351/241/271/347/233/256/344/270/216/350/203/275/345/212/233/346/230/240/345/260/204/347/237/251/351/230/265@3x.png +0 -0
- package/src/statics/icons/childIcons/PV-3/351/241/271/347/233/256/344/270/216/350/203/275/345/212/233/347/232/204/346/230/240/345/260/204/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-1 /347/263/273/347/273/237/346/216/245/345/217/243/345/206/205/351/203/250/346/217/217/350/277/260/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-1 /347/263/273/347/273/237/346/216/245/345/217/243/346/217/217/350/277/260/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-10a /347/263/273/347/273/237/345/217/202/346/225/260/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-10a /347/263/273/347/273/237/350/247/204/345/210/231/346/250/241/345/236/213/350/241/250@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-10a/347/263/273/347/273/237/350/247/204/345/210/231/346/250/241/345/236/213/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-10b /347/263/273/347/273/237/347/212/266/346/200/201/350/275/254/346/215/242/346/217/217/350/277/260/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-10b/347/263/273/347/273/237/347/212/266/346/200/201/350/275/254/346/215/242/346/217/217/350/277/260/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-10c /347/263/273/347/273/237/344/272/213/344/273/266/350/267/237/350/270/252/346/217/217/350/277/260/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-10c/347/263/273/347/273/237/344/272/213/344/273/266-/350/277/275/350/270/252/346/217/217/350/277/260/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-1/347/263/273/347/273/237/346/216/245/345/217/243/346/217/217/350/277/260/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-2 /347/263/273/347/273/237/345/206/205/351/203/250/350/265/204/346/272/220/346/265/201/345/212/250/346/217/217/350/277/260/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-2 /347/263/273/347/273/237/350/265/204/346/272/220/346/265/201/345/212/250/346/217/217/350/277/260/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-2/347/263/273/347/273/237/350/265/204/346/272/220/346/265/201/346/217/217/350/277/260/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-3 /347/263/273/347/273/237 - /347/263/273/347/273/237/347/237/251/351/230/265@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-3/347/263/273/347/273/237-/347/263/273/347/273/237/347/237/251/351/230/265/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-4 /347/263/273/347/273/237/345/212/237/350/203/275/346/217/217/350/277/260/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-4 /347/263/273/347/273/237/345/212/237/350/203/275/346/265/201/347/250/213/346/217/217/350/277/260/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-4/347/263/273/347/273/237/345/212/237/350/203/275/346/217/217/350/277/260/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-5a /344/270/232/345/212/241/346/264/273/345/212/250/345/210/260/347/263/273/347/273/237/345/212/237/350/203/275/347/232/204/345/217/257/350/277/275/346/272/257/346/200/247/347/237/251/351/230/265@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-5a/344/275/234/346/210/230/346/264/273/345/212/250/345/210/260/347/263/273/347/273/237/345/212/237/350/203/275/345/217/257/350/277/275/350/270/252/347/237/251/351/230/265/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-5b /344/270/232/345/212/241/346/264/273/345/212/250/345/210/260/347/263/273/347/273/237/347/232/204/345/217/257/350/277/275/346/272/257/346/200/247/347/237/251/351/230/265@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-5b/344/275/234/346/210/230/346/264/273/345/212/250/345/210/260/347/263/273/347/273/237/345/217/257/350/277/275/350/270/252/347/237/251/351/230/265/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-6 /347/263/273/347/273/237/350/265/204/346/272/220/346/265/201/345/212/250/347/237/251/351/230/265@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-6/347/263/273/347/273/237/350/265/204/346/272/220/346/265/201/347/237/251/351/230/265/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-7 /347/263/273/347/273/237/345/256/236/351/231/205/345/272/246/351/207/217/347/237/251/351/230/265@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-7/347/263/273/347/273/237/345/272/246/351/207/217/347/237/251/351/230/265/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-8 /347/263/273/347/273/237/346/274/224/350/277/233/346/217/217/350/277/260/347/224/230/347/211/271/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-8/347/263/273/347/273/237/346/274/224/350/277/233/346/217/217/350/277/260/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-9 /347/263/273/347/273/237/346/212/200/346/234/257/344/270/216/346/212/200/350/203/275/351/242/204/346/265/213/350/241/250@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-9/347/263/273/347/273/237/346/212/200/346/234/257/344/270/216/346/212/200/350/203/275/351/242/204/346/265/213/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/StdV-1 /346/240/207/345/207/206/351/205/215/347/275/256/350/241/250@3x.png +0 -0
- package/src/statics/icons/childIcons/StdV-1/346/240/207/345/207/206/351/205/215/347/275/256/346/226/207/344/273/266/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/StdV-2 /346/240/207/345/207/206/351/242/204/346/265/213/350/241/250@3x.png +0 -0
- package/src/statics/icons/childIcons/StdV-2/346/240/207/345/207/206/351/242/204/346/265/213/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-10a /346/234/215/345/212/241/345/217/202/346/225/260/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-10a/346/234/215/345/212/241/350/247/204/345/210/231/346/250/241/345/236/213/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-10b /346/234/215/345/212/241/347/212/266/346/200/201/350/275/254/346/215/242/346/217/217/350/277/260/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-10b/346/234/215/345/212/241/347/212/266/346/200/201/350/275/254/346/215/242/346/217/217/350/277/260/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-10c /346/234/215/345/212/241/344/272/213/344/273/266/350/267/237/350/270/252/346/217/217/350/277/260/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-10c/346/234/215/345/212/241/344/272/213/344/273/266-/350/277/275/350/270/252/346/217/217/350/277/260/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-1/346/234/215/345/212/241/344/270/212/344/270/213/346/226/207/346/217/217/350/277/260/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-1/346/234/215/345/212/241/350/203/214/346/231/257/346/250/241/345/236/213/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-2 /346/234/215/345/212/241/350/265/204/346/272/220/346/265/201/346/217/217/350/277/260/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-2/346/234/215/345/212/241/350/265/204/346/272/220/346/265/201/346/217/217/350/277/260/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-3a /347/263/273/347/273/237 -/346/234/215/345/212/241/347/237/251/351/230/265@3x-2.png +0 -0
- package/src/statics/icons/childIcons/SvcV-3a /347/263/273/347/273/237 -/346/234/215/345/212/241/347/237/251/351/230/265@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-3a/347/263/273/347/273/237-/346/234/215/345/212/241/347/237/251/351/230/265/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-3b/346/234/215/345/212/241-/346/234/215/345/212/241/347/237/251/351/230/265/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-4 /346/234/215/345/212/241/345/212/237/350/203/275/346/217/217/350/277/260/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-4 /346/234/215/345/212/241/345/212/237/350/203/275/346/265/201/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-4/346/234/215/345/212/241/345/212/237/350/203/275/346/217/217/350/277/260/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-5/344/275/234/346/210/230/346/264/273/345/212/250/345/210/260/346/234/215/345/212/241/345/217/257/350/277/275/350/270/252/347/237/251/351/230/265/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-6 /346/234/215/345/212/241/350/265/204/346/272/220/346/265/201/347/237/251/351/230/265@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-6/346/234/215/345/212/241/350/265/204/346/272/220/346/265/201/347/237/251/351/230/265/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-7 /346/234/215/345/212/241/345/205/270/345/236/213/345/272/246/351/207/217/347/237/251/351/230/265@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-7/346/234/215/345/212/241/345/272/246/351/207/217/347/237/251/351/230/265/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-8 /346/234/215/345/212/241/346/274/224/350/277/233/347/224/230/347/211/271/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-8/346/234/215/345/212/241/346/274/224/350/277/233/346/217/217/350/277/260/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-9 /346/234/215/345/212/241/346/212/200/346/234/257/344/270/216/346/212/200/350/203/275/351/242/204/346/265/213/350/241/250@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-9/346/234/215/345/212/241/346/212/200/346/234/257/344/270/216/346/212/200/350/203/275/351/242/204/346/265/213/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons//344/275/223/347/263/273/346/236/266/346/236/204@3x.png +0 -0
- package/src/statics/icons/childIcons//344/275/234/346/210/230/350/247/206/350/247/222@3x.png +0 -0
- package/src/statics/icons/childIcons//345/205/250/346/231/257/350/247/206/350/247/222@3x.png +0 -0
- package/src/statics/icons/childIcons//345/205/254/345/217/270@3x.png +0 -0
- package/src/statics/icons/childIcons//345/215/217/350/256/256@3x.png +0 -0
- package/src/statics/icons/childIcons//345/215/217/350/256/256/345/261/202@3x.png +0 -0
- package/src/statics/icons/childIcons//345/215/217/350/256/256/346/240/210@3x.png +0 -0
- package/src/statics/icons/childIcons//345/221/275/344/273/244@3x.png +0 -0
- package/src/statics/icons/childIcons//346/210/230/347/225/245/346/246/202/345/277/265/350/241/250@3x.png +0 -0
- package/src/statics/icons/childIcons//346/216/247/345/210/266@3x.png +0 -0
- package/src/statics/icons/childIcons//346/224/257/346/214/201@3x.png +0 -0
- package/src/statics/icons/childIcons//346/225/260/346/215/256/344/277/241/346/201/257/350/247/206/350/247/222@3x.png +0 -0
- package/src/statics/icons/childIcons//346/234/215/345/212/241/350/247/206/350/247/222@3x.png +0 -0
- package/src/statics/icons/childIcons//346/240/207/345/207/206@3x.png +0 -0
- package/src/statics/icons/childIcons//346/240/207/345/207/206/350/247/206/350/247/222@3x.png +0 -0
- package/src/statics/icons/childIcons//347/263/273/347/273/237/350/247/206/350/247/222@3x.png +0 -0
- package/src/statics/icons/childIcons//350/203/275/345/212/233/350/247/206/350/247/222@3x.png +0 -0
- package/src/statics/icons/childIcons//351/241/271/347/233/256/350/247/206/350/247/222@3x.png +0 -0
- package/src/statics/icons/createMenu/down.png +0 -0
- package/src/statics/icons/createMenu/remove.png +0 -0
- package/src/statics/icons/createMenu/up.png +0 -0
- package/src/store/graphStore.ts +238 -45
- package/src/types/index.ts +87 -4
- package/src/utils/batchAutoExpand.ts +9 -10
- package/src/utils/containers.ts +72 -17
- package/src/utils/contextMenuUtils.ts +7 -7
- package/src/utils/dateUtils.ts +160 -0
- package/src/utils/diagram.ts +10 -8
- package/src/utils/drag.ts +6 -5
- package/src/utils/edgeUtils.ts +344 -427
- package/src/utils/edgeWorker.ts +471 -0
- package/src/utils/hittest.ts +37 -38
- package/src/utils/index.ts +3 -0
- package/src/utils/keyboardUtils.ts +5 -5
- package/src/utils/packageOutline.ts +96 -0
- package/src/utils/rafThrottle.ts +162 -0
- package/src/utils/workerManager.ts +335 -0
- package/src/view/graph.vue +47 -33
- /package/src/statics/icons/childIcons//346/210/230/347/225/{245@3x.png" → 245/345/261/202@3x.png"} +0 -0
package/src/utils/edgeUtils.ts
CHANGED
|
@@ -1,30 +1,59 @@
|
|
|
1
1
|
// edge-utils.ts
|
|
2
|
-
import type { Shape } from "../types";
|
|
2
|
+
import type { Shape, Waypoint } from "../types";
|
|
3
3
|
import { pickTarget } from "./hittest";
|
|
4
4
|
import { useGraphStore } from '../store/graphStore';
|
|
5
5
|
import { snapPinToParentEdge } from './pinUtils';
|
|
6
6
|
import type { IHighlightUtils } from "../hooks/useHighlight";
|
|
7
|
+
import { workerManager } from './workerManager';
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
export class EdgeUtils {
|
|
10
11
|
/**
|
|
11
|
-
*
|
|
12
|
+
* 更新与指定图元相关的连线端点(同步版本)
|
|
12
13
|
* @param shapes 所有图元
|
|
13
14
|
* @param changedIds 发生变化的图元ID列表
|
|
14
15
|
* @param updateShape 更新图元的回调函数
|
|
16
|
+
* @param edgeIndex 可选,nodeId → 关联 edges 的索引(来自 graphStore.edgesByNodeId)
|
|
17
|
+
* @param shapeMapIndex 可选,id → Shape 的索引(来自 graphStore.shapeMap)
|
|
15
18
|
*/
|
|
16
19
|
static updateRelatedEdges(
|
|
17
20
|
shapes: Shape[],
|
|
18
21
|
changedIds: string[],
|
|
19
|
-
updateShape: (shape: Shape) => void
|
|
22
|
+
updateShape: (shape: Shape) => void,
|
|
23
|
+
edgeIndex?: Map<string, Shape[]>,
|
|
24
|
+
shapeMapIndex?: Map<string, Shape>
|
|
20
25
|
) {
|
|
21
|
-
|
|
26
|
+
// 收集与 changedIds 相关的所有 edge(去重)
|
|
27
|
+
let relatedEdges: Shape[]
|
|
28
|
+
if (edgeIndex) {
|
|
29
|
+
const seen = new Set<string>()
|
|
30
|
+
relatedEdges = []
|
|
31
|
+
for (const id of changedIds) {
|
|
32
|
+
const edges = edgeIndex.get(id)
|
|
33
|
+
if (edges) {
|
|
34
|
+
for (const e of edges) {
|
|
35
|
+
if (!seen.has(e.id)) {
|
|
36
|
+
seen.add(e.id)
|
|
37
|
+
relatedEdges.push(e)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
// 回退:全量 filter
|
|
44
|
+
relatedEdges = shapes.filter((shape) => shape.shapeType === "edge")
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 用于 O(1) 查找 source/target shape
|
|
48
|
+
const findShape = shapeMapIndex
|
|
49
|
+
? (id: string) => shapeMapIndex.get(id) ?? null
|
|
50
|
+
: (id: string) => shapes.find(s => s.id === id) ?? null
|
|
22
51
|
|
|
23
52
|
// 按源-目标对分组,为每组中的线条生成不同的偏移
|
|
24
53
|
// 同时处理反向连接(A→B 和 B→A)的情况
|
|
25
54
|
const edgeGroups = new Map<string, Shape[]>();
|
|
26
55
|
|
|
27
|
-
|
|
56
|
+
relatedEdges.forEach((edge) => {
|
|
28
57
|
if (edge.sourceId && edge.targetId) {
|
|
29
58
|
// 创建源-目标对的规范化键(确保 A-B 和 B-A 使用相同的键)
|
|
30
59
|
const isForward = edge.sourceId.localeCompare(edge.targetId) <= 0;
|
|
@@ -39,76 +68,28 @@ export class EdgeUtils {
|
|
|
39
68
|
}
|
|
40
69
|
});
|
|
41
70
|
|
|
71
|
+
const changedSet = new Set(changedIds)
|
|
72
|
+
|
|
42
73
|
// 处理每个分组
|
|
43
74
|
edgeGroups.forEach((groupEdges, groupKey) => {
|
|
44
75
|
if (groupEdges.length > 1) {
|
|
45
76
|
// 如果同一源-目标对有多个线条,为每条线生成不同的偏移
|
|
46
77
|
groupEdges.forEach((edge, index) => {
|
|
47
|
-
const sourceChanged = edge.sourceId &&
|
|
48
|
-
const targetChanged = edge.targetId &&
|
|
78
|
+
const sourceChanged = edge.sourceId && changedSet.has(edge.sourceId);
|
|
79
|
+
const targetChanged = edge.targetId && changedSet.has(edge.targetId);
|
|
49
80
|
|
|
50
81
|
if (sourceChanged || targetChanged) {
|
|
51
|
-
const sourceShape =
|
|
52
|
-
const targetShape =
|
|
82
|
+
const sourceShape = edge.sourceId ? findShape(edge.sourceId) : null;
|
|
83
|
+
const targetShape = edge.targetId ? findShape(edge.targetId) : null;
|
|
53
84
|
|
|
54
85
|
if (sourceShape && targetShape && sourceShape.bounds && targetShape.bounds) {
|
|
55
|
-
//
|
|
56
|
-
const {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
// 计算连接方向
|
|
64
|
-
const dx = targetCenter.x - sourceCenter.x;
|
|
65
|
-
const dy = targetCenter.y - sourceCenter.y;
|
|
66
|
-
|
|
67
|
-
// 生成基于索引的偏移量(小到不会明显影响,但足以分开线条)
|
|
68
|
-
const offsetDistance = 5 * (index + 1);
|
|
69
|
-
|
|
70
|
-
// 根据方向计算偏移方向
|
|
71
|
-
let offsetX = 0, offsetY = 0;
|
|
72
|
-
if (Math.abs(dx) > Math.abs(dy)) {
|
|
73
|
-
// 水平方向为主,垂直偏移
|
|
74
|
-
offsetY = offsetDistance;
|
|
75
|
-
} else {
|
|
76
|
-
// 垂直方向为主,水平偏移
|
|
77
|
-
offsetX = offsetDistance;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// 确保线条交替偏移方向,避免全部偏向一侧
|
|
81
|
-
if (index % 2 === 1) {
|
|
82
|
-
offsetX = -offsetX;
|
|
83
|
-
offsetY = -offsetY;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// 确定连接点,添加偏移
|
|
87
|
-
let sourcePoint, targetPoint;
|
|
88
|
-
|
|
89
|
-
if (Math.abs(dx) > Math.abs(dy)) {
|
|
90
|
-
// 水平方向
|
|
91
|
-
sourcePoint = dx > 0
|
|
92
|
-
? { x: sx + sw, y: sourceCenter.y + offsetY }
|
|
93
|
-
: { x: sx, y: sourceCenter.y + offsetY };
|
|
94
|
-
|
|
95
|
-
targetPoint = dx > 0
|
|
96
|
-
? { x: tx, y: targetCenter.y + offsetY }
|
|
97
|
-
: { x: tx + tw, y: targetCenter.y + offsetY };
|
|
98
|
-
} else {
|
|
99
|
-
// 垂直方向
|
|
100
|
-
sourcePoint = dy > 0
|
|
101
|
-
? { x: sourceCenter.x + offsetX, y: sy + sh }
|
|
102
|
-
: { x: sourceCenter.x + offsetX, y: sy };
|
|
103
|
-
|
|
104
|
-
targetPoint = dy > 0
|
|
105
|
-
? { x: targetCenter.x + offsetX, y: ty }
|
|
106
|
-
: { x: targetCenter.x + offsetX, y: ty + th };
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// 更新连线,只使用源点和目标点确保线条保持直线
|
|
110
|
-
// 通过调整端点位置而不是添加中间点来避免线条重叠
|
|
111
|
-
const waypoints = [sourcePoint, targetPoint];
|
|
86
|
+
// 使用最短距离边中点算法(与 completeConnection 一致)
|
|
87
|
+
const { waypoints } = this.buildEdgeWaypoints(
|
|
88
|
+
sourceShape.bounds,
|
|
89
|
+
targetShape.bounds,
|
|
90
|
+
index,
|
|
91
|
+
sourceShape.id === targetShape.id
|
|
92
|
+
);
|
|
112
93
|
|
|
113
94
|
const updatedEdge = {
|
|
114
95
|
...edge,
|
|
@@ -120,54 +101,27 @@ export class EdgeUtils {
|
|
|
120
101
|
}
|
|
121
102
|
});
|
|
122
103
|
} else {
|
|
123
|
-
//
|
|
104
|
+
// 单线条情况
|
|
124
105
|
const edge = groupEdges[0];
|
|
125
|
-
const sourceChanged = edge.sourceId &&
|
|
126
|
-
const targetChanged = edge.targetId &&
|
|
106
|
+
const sourceChanged = edge.sourceId && changedSet.has(edge.sourceId);
|
|
107
|
+
const targetChanged = edge.targetId && changedSet.has(edge.targetId);
|
|
127
108
|
|
|
128
109
|
if (sourceChanged || targetChanged) {
|
|
129
|
-
const sourceShape =
|
|
130
|
-
const targetShape =
|
|
110
|
+
const sourceShape = edge.sourceId ? findShape(edge.sourceId) : null;
|
|
111
|
+
const targetShape = edge.targetId ? findShape(edge.targetId) : null;
|
|
131
112
|
|
|
132
113
|
if (sourceShape && targetShape && sourceShape.bounds && targetShape.bounds) {
|
|
133
|
-
|
|
134
|
-
const {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
// 计算连接方向
|
|
141
|
-
const dx = targetCenter.x - sourceCenter.x;
|
|
142
|
-
const dy = targetCenter.y - sourceCenter.y;
|
|
143
|
-
|
|
144
|
-
// 确定连接点
|
|
145
|
-
let sourcePoint, targetPoint;
|
|
146
|
-
|
|
147
|
-
if (Math.abs(dx) > Math.abs(dy)) {
|
|
148
|
-
// 水平方向
|
|
149
|
-
sourcePoint = dx > 0
|
|
150
|
-
? { x: sx + sw, y: sourceCenter.y }
|
|
151
|
-
: { x: sx, y: sourceCenter.y };
|
|
152
|
-
|
|
153
|
-
targetPoint = dx > 0
|
|
154
|
-
? { x: tx, y: targetCenter.y }
|
|
155
|
-
: { x: tx + tw, y: targetCenter.y };
|
|
156
|
-
} else {
|
|
157
|
-
// 垂直方向
|
|
158
|
-
sourcePoint = dy > 0
|
|
159
|
-
? { x: sourceCenter.x, y: sy + sh }
|
|
160
|
-
: { x: sourceCenter.x, y: sy };
|
|
161
|
-
|
|
162
|
-
targetPoint = dy > 0
|
|
163
|
-
? { x: targetCenter.x, y: ty }
|
|
164
|
-
: { x: targetCenter.x, y: ty + th };
|
|
165
|
-
}
|
|
114
|
+
// 使用最短距离边中点算法(与 completeConnection 一致),index=0 无偏移
|
|
115
|
+
const { waypoints } = this.buildEdgeWaypoints(
|
|
116
|
+
sourceShape.bounds,
|
|
117
|
+
targetShape.bounds,
|
|
118
|
+
0,
|
|
119
|
+
sourceShape.id === targetShape.id
|
|
120
|
+
);
|
|
166
121
|
|
|
167
|
-
// 更新连线
|
|
168
122
|
const updatedEdge = {
|
|
169
123
|
...edge,
|
|
170
|
-
waypointId: JSON.stringify(
|
|
124
|
+
waypointId: JSON.stringify(waypoints),
|
|
171
125
|
};
|
|
172
126
|
|
|
173
127
|
updateShape(updatedEdge);
|
|
@@ -177,6 +131,46 @@ export class EdgeUtils {
|
|
|
177
131
|
});
|
|
178
132
|
}
|
|
179
133
|
|
|
134
|
+
/**
|
|
135
|
+
* 更新与指定图元相关的连线端点(异步版本,使用 Web Worker)
|
|
136
|
+
* 内置竞态控制:如果在 Worker 返回前又发起了新的调用,旧结果会被丢弃。
|
|
137
|
+
* @param shapes 所有图元
|
|
138
|
+
* @param changedIds 发生变化的图元ID列表
|
|
139
|
+
* @param updateShape 更新图元的回调函数
|
|
140
|
+
* @param edgeIndex 可选,nodeId → 关联 edges 的索引(来自 graphStore.edgesByNodeId)
|
|
141
|
+
* @param shapeMapIndex 可选,id → Shape 的索引(来自 graphStore.shapeMap)
|
|
142
|
+
*/
|
|
143
|
+
static async updateRelatedEdgesAsync(
|
|
144
|
+
shapes: Shape[],
|
|
145
|
+
changedIds: string[],
|
|
146
|
+
updateShape: (shape: Shape) => void,
|
|
147
|
+
edgeIndex?: Map<string, Shape[]>,
|
|
148
|
+
shapeMapIndex?: Map<string, Shape>
|
|
149
|
+
): Promise<void> {
|
|
150
|
+
try {
|
|
151
|
+
const { version, result: updatedEdges } = await workerManager.updateRelatedEdges(
|
|
152
|
+
shapes,
|
|
153
|
+
changedIds,
|
|
154
|
+
edgeIndex,
|
|
155
|
+
shapeMapIndex
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
// 竞态保护:只采纳最新版本的结果,丢弃过期计算
|
|
159
|
+
if (!workerManager.isLatestVersion('updateRelatedEdges', version)) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// 更新所有返回的边缘
|
|
164
|
+
updatedEdges.forEach((edge: Shape) => {
|
|
165
|
+
updateShape(edge);
|
|
166
|
+
});
|
|
167
|
+
} catch (error) {
|
|
168
|
+
console.error('Error in updateRelatedEdgesAsync:', error);
|
|
169
|
+
// 回退到同步版本
|
|
170
|
+
this.updateRelatedEdges(shapes, changedIds, updateShape, edgeIndex, shapeMapIndex);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
180
174
|
/**
|
|
181
175
|
* 获取图形的四个中心点(上下左右)
|
|
182
176
|
*/
|
|
@@ -208,14 +202,153 @@ export class EdgeUtils {
|
|
|
208
202
|
}
|
|
209
203
|
|
|
210
204
|
/**
|
|
211
|
-
*
|
|
205
|
+
* 生成图元自连接时使用的半环路径。
|
|
206
|
+
* 路径使用正交折线,从图元上边中点出发,沿右侧绕到下边中点,
|
|
207
|
+
* 让自连接的观感更接近矩形转角线。
|
|
208
|
+
*/
|
|
209
|
+
static buildSelfLoopWaypoints(
|
|
210
|
+
bounds: { x?: number; y?: number; width?: number; height?: number },
|
|
211
|
+
groupIndex: number = 0
|
|
212
|
+
): {
|
|
213
|
+
sourcePoint: { x: number; y: number };
|
|
214
|
+
targetPoint: { x: number; y: number };
|
|
215
|
+
waypoints: Waypoint[];
|
|
216
|
+
} {
|
|
217
|
+
const safeBounds = {
|
|
218
|
+
x: bounds.x ?? 0,
|
|
219
|
+
y: bounds.y ?? 0,
|
|
220
|
+
width: bounds.width ?? 0,
|
|
221
|
+
height: bounds.height ?? 0,
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
const { x, y, width, height } = safeBounds;
|
|
225
|
+
const centerX = x + width / 2;
|
|
226
|
+
const sourcePoint = { x: centerX, y };
|
|
227
|
+
const targetPoint = { x: centerX, y: y + height };
|
|
228
|
+
|
|
229
|
+
// 保持上下抬升高度不变,只缩短右侧外扩距离,让右边那段线更贴近图元。
|
|
230
|
+
const outwardOffset = Math.max(width * 0.24, 20) + groupIndex * 12;
|
|
231
|
+
const verticalPadding = Math.max(height * 0.45, 26) + groupIndex * 10;
|
|
232
|
+
const upperPoint = {
|
|
233
|
+
x: centerX,
|
|
234
|
+
y: y - verticalPadding,
|
|
235
|
+
};
|
|
236
|
+
const upperRightPoint = {
|
|
237
|
+
x: x + width + outwardOffset,
|
|
238
|
+
y: y - verticalPadding,
|
|
239
|
+
};
|
|
240
|
+
const lowerRightPoint = {
|
|
241
|
+
x: x + width + outwardOffset,
|
|
242
|
+
y: y + height + verticalPadding,
|
|
243
|
+
};
|
|
244
|
+
const lowerPoint = {
|
|
245
|
+
x: centerX,
|
|
246
|
+
y: y + height + verticalPadding,
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
sourcePoint,
|
|
251
|
+
targetPoint,
|
|
252
|
+
waypoints: [sourcePoint, upperPoint, upperRightPoint, lowerRightPoint, lowerPoint, targetPoint],
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* 统一生成边的折点数据。
|
|
258
|
+
* 普通连线仍使用最近边中点,自连接则走专用半环路径。
|
|
259
|
+
*/
|
|
260
|
+
static buildEdgeWaypoints(
|
|
261
|
+
sBounds: { x?: number; y?: number; width?: number; height?: number },
|
|
262
|
+
tBounds: { x?: number; y?: number; width?: number; height?: number },
|
|
263
|
+
groupIndex: number,
|
|
264
|
+
isSelfLoop: boolean
|
|
265
|
+
): {
|
|
266
|
+
sourcePoint: { x: number; y: number };
|
|
267
|
+
targetPoint: { x: number; y: number };
|
|
268
|
+
waypoints: Waypoint[];
|
|
269
|
+
} {
|
|
270
|
+
if (isSelfLoop) {
|
|
271
|
+
return this.buildSelfLoopWaypoints(sBounds, groupIndex);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const { sourcePoint, targetPoint } = this.calcBestEndpoints(
|
|
275
|
+
sBounds,
|
|
276
|
+
tBounds,
|
|
277
|
+
groupIndex
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
return {
|
|
281
|
+
sourcePoint,
|
|
282
|
+
targetPoint,
|
|
283
|
+
waypoints: [sourcePoint, targetPoint],
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* 计算两个图元之间的最佳连接端点(共用算法)
|
|
289
|
+
* 使用 4×4 边中点最短距离组合,与 completeConnection 保持一致。
|
|
290
|
+
* @param sBounds 源图元 bounds
|
|
291
|
+
* @param tBounds 目标图元 bounds
|
|
292
|
+
* @param groupIndex 同源-目标对中的索引,0 表示无偏移
|
|
293
|
+
*/
|
|
294
|
+
static calcBestEndpoints(
|
|
295
|
+
sBounds: { x?: number; y?: number; width?: number; height?: number },
|
|
296
|
+
tBounds: { x?: number; y?: number; width?: number; height?: number },
|
|
297
|
+
groupIndex: number
|
|
298
|
+
): { sourcePoint: { x: number; y: number }; targetPoint: { x: number; y: number } } {
|
|
299
|
+
const sb = { x: sBounds.x ?? 0, y: sBounds.y ?? 0, width: sBounds.width ?? 0, height: sBounds.height ?? 0 };
|
|
300
|
+
const tb = { x: tBounds.x ?? 0, y: tBounds.y ?? 0, width: tBounds.width ?? 0, height: tBounds.height ?? 0 };
|
|
301
|
+
const sourcePoints = this.getShapeCenterPoints(sb);
|
|
302
|
+
const targetPoints = this.getShapeCenterPoints(tb);
|
|
303
|
+
|
|
304
|
+
// 4×4 组合取最短距离
|
|
305
|
+
let minDist = Infinity;
|
|
306
|
+
let bestSrc = sourcePoints.top;
|
|
307
|
+
let bestTgt = targetPoints.top;
|
|
308
|
+
for (const sp of Object.values(sourcePoints)) {
|
|
309
|
+
for (const tp of Object.values(targetPoints)) {
|
|
310
|
+
const d = this.getDistance(sp, tp);
|
|
311
|
+
if (d < minDist) {
|
|
312
|
+
minDist = d;
|
|
313
|
+
bestSrc = sp;
|
|
314
|
+
bestTgt = tp;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// 多线偏移
|
|
320
|
+
if (groupIndex > 0) {
|
|
321
|
+
const dx = (tb.x + tb.width / 2) - (sb.x + sb.width / 2);
|
|
322
|
+
const dy = (tb.y + tb.height / 2) - (sb.y + sb.height / 2);
|
|
323
|
+
const offsetDistance = 5 * (groupIndex + 1);
|
|
324
|
+
let offsetX = 0, offsetY = 0;
|
|
325
|
+
if (Math.abs(dx) > Math.abs(dy)) {
|
|
326
|
+
offsetY = offsetDistance;
|
|
327
|
+
} else {
|
|
328
|
+
offsetX = offsetDistance;
|
|
329
|
+
}
|
|
330
|
+
if (groupIndex % 2 === 1) {
|
|
331
|
+
offsetX = -offsetX;
|
|
332
|
+
offsetY = -offsetY;
|
|
333
|
+
}
|
|
334
|
+
return {
|
|
335
|
+
sourcePoint: { x: bestSrc.x + offsetX, y: bestSrc.y + offsetY },
|
|
336
|
+
targetPoint: { x: bestTgt.x + offsetX, y: bestTgt.y + offsetY },
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return { sourcePoint: bestSrc, targetPoint: bestTgt };
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* 找到距离鼠标位置最近的连接点(同步版本)
|
|
212
345
|
*/
|
|
213
346
|
static findNearestConnectPoint(
|
|
214
347
|
mousePos: { x: number; y: number },
|
|
215
348
|
shape: Shape | undefined,
|
|
216
|
-
diagramBounds
|
|
349
|
+
diagramBounds?: any
|
|
217
350
|
) {
|
|
218
|
-
if (!shape?.bounds
|
|
351
|
+
if (!shape?.bounds) return null;
|
|
219
352
|
|
|
220
353
|
const mouseX = mousePos.x;
|
|
221
354
|
const mouseY = mousePos.y;
|
|
@@ -290,6 +423,22 @@ export class EdgeUtils {
|
|
|
290
423
|
}
|
|
291
424
|
}
|
|
292
425
|
|
|
426
|
+
/**
|
|
427
|
+
* 找到距离鼠标位置最近的连接点(异步版本,使用 Web Worker)
|
|
428
|
+
*/
|
|
429
|
+
static async findNearestConnectPointAsync(
|
|
430
|
+
mousePos: { x: number; y: number },
|
|
431
|
+
shape: Shape | undefined
|
|
432
|
+
): Promise<any> {
|
|
433
|
+
try {
|
|
434
|
+
return await workerManager.findNearestConnectPoint(mousePos, shape);
|
|
435
|
+
} catch (error) {
|
|
436
|
+
console.error('Error in findNearestConnectPointAsync:', error);
|
|
437
|
+
// 回退到同步版本(这里简化处理,不传递 diagramBounds)
|
|
438
|
+
return this.findNearestConnectPoint(mousePos, shape, null);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
293
442
|
/**
|
|
294
443
|
* 完成连接操作,计算最终连接点
|
|
295
444
|
*/
|
|
@@ -298,223 +447,63 @@ export class EdgeUtils {
|
|
|
298
447
|
targetShape: Shape,
|
|
299
448
|
clickPoint: { x: number; y: number },
|
|
300
449
|
currentConnectPoint: { x: number; y: number },
|
|
301
|
-
shapes: Shape[] = []
|
|
450
|
+
shapes: Shape[] = []
|
|
302
451
|
) {
|
|
303
|
-
//
|
|
304
|
-
if (sourceShape?.id && targetShape.id && sourceShape.id === targetShape.id) {
|
|
305
|
-
return null;
|
|
306
|
-
}
|
|
307
|
-
|
|
452
|
+
// 自连接不再直接拦截,而是交给专用的半环路径逻辑处理。
|
|
308
453
|
if (!targetShape.bounds || !sourceShape?.bounds) return null;
|
|
309
454
|
|
|
310
|
-
//
|
|
311
|
-
const { x: sx = 0, y: sy = 0, width: sw = 0, height: sh = 0 } = sourceShape.bounds;
|
|
312
|
-
const { x: tx = 0, y: ty = 0, width: tw = 0, height: th = 0 } = targetShape.bounds;
|
|
313
|
-
|
|
314
|
-
const sourceCenter = { x: sx + sw / 2, y: sy + sh / 2 };
|
|
315
|
-
const targetCenter = { x: tx + tw / 2, y: ty + th / 2 };
|
|
316
|
-
|
|
317
|
-
// 获取两个图元的所有边中点
|
|
318
|
-
const sourcePoints = this.getShapeCenterPoints({
|
|
319
|
-
x: sourceShape.bounds.x ?? 0,
|
|
320
|
-
y: sourceShape.bounds.y ?? 0,
|
|
321
|
-
width: sourceShape.bounds.width ?? 0,
|
|
322
|
-
height: sourceShape.bounds.height ?? 0,
|
|
323
|
-
});
|
|
324
|
-
const targetPoints = this.getShapeCenterPoints({
|
|
325
|
-
x: targetShape.bounds.x ?? 0,
|
|
326
|
-
y: targetShape.bounds.y ?? 0,
|
|
327
|
-
width: targetShape.bounds.width ?? 0,
|
|
328
|
-
height: targetShape.bounds.height ?? 0,
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
// 找出源图元和目标图元之间距离最短的边中点组合
|
|
332
|
-
let minDistance = Infinity;
|
|
333
|
-
let bestSourcePoint = sourcePoints.top; // 默认值
|
|
334
|
-
let bestTargetPoint = targetPoints.top; // 默认值
|
|
335
|
-
|
|
336
|
-
// 遍历所有可能的源点和目标点组合
|
|
337
|
-
Object.values(sourcePoints).forEach(sourcePoint => {
|
|
338
|
-
Object.values(targetPoints).forEach(targetPoint => {
|
|
339
|
-
const distance = this.getDistance(sourcePoint, targetPoint);
|
|
340
|
-
if (distance < minDistance) {
|
|
341
|
-
minDistance = distance;
|
|
342
|
-
bestSourcePoint = sourcePoint;
|
|
343
|
-
bestTargetPoint = targetPoint;
|
|
344
|
-
}
|
|
345
|
-
});
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
// 使用最短距离的点作为连接点
|
|
349
|
-
const startPoint = bestSourcePoint;
|
|
350
|
-
let targetPoint = bestTargetPoint;
|
|
351
|
-
|
|
352
|
-
// 以下是原始代码,保留以处理特殊情况(如果需要的话)
|
|
353
|
-
/*
|
|
354
|
-
const { x = 0, y = 0, width = 0, height = 0 } = targetShape.bounds;
|
|
355
|
-
|
|
356
|
-
const left = x;
|
|
357
|
-
const right = x + width;
|
|
358
|
-
const top = y;
|
|
359
|
-
const bottom = y + height;
|
|
360
|
-
|
|
361
|
-
const relativeX = clickPoint.x - x;
|
|
362
|
-
const relativeY = clickPoint.y - y;
|
|
363
|
-
|
|
364
|
-
const isInTopArea = relativeY < 0;
|
|
365
|
-
const isInBottomArea = relativeY > height;
|
|
366
|
-
const isInLeftArea = relativeX < 0;
|
|
367
|
-
const isInRightArea = relativeX > width;
|
|
368
|
-
|
|
369
|
-
if (isInTopArea) {
|
|
370
|
-
const constrainedX = Math.max(left, Math.min(right, clickPoint.x));
|
|
371
|
-
targetPoint = { x: constrainedX, y: top };
|
|
372
|
-
} else if (isInBottomArea) {
|
|
373
|
-
const constrainedX = Math.max(left, Math.min(right, clickPoint.x));
|
|
374
|
-
targetPoint = { x: constrainedX, y: bottom };
|
|
375
|
-
} else if (isInLeftArea) {
|
|
376
|
-
const constrainedY = Math.max(top, Math.min(bottom, clickPoint.y));
|
|
377
|
-
targetPoint = { x: left, y: constrainedY };
|
|
378
|
-
} else if (isInRightArea) {
|
|
379
|
-
const constrainedY = Math.max(top, Math.min(bottom, clickPoint.y));
|
|
380
|
-
targetPoint = { x: right, y: constrainedY };
|
|
381
|
-
} else {
|
|
382
|
-
const distances = {
|
|
383
|
-
top: Math.abs(clickPoint.y - top),
|
|
384
|
-
bottom: Math.abs(clickPoint.y - bottom),
|
|
385
|
-
left: Math.abs(clickPoint.x - left),
|
|
386
|
-
right: Math.abs(clickPoint.x - right),
|
|
387
|
-
};
|
|
388
|
-
|
|
389
|
-
const nearestEdge = Object.entries(distances).reduce(
|
|
390
|
-
(min, [key, distance]) =>
|
|
391
|
-
distance < min.distance ? { key, distance } : min,
|
|
392
|
-
{ key: "top", distance: Infinity }
|
|
393
|
-
);
|
|
394
|
-
|
|
395
|
-
switch (nearestEdge.key) {
|
|
396
|
-
case "top":
|
|
397
|
-
targetPoint = { x: clickPoint.x, y: top };
|
|
398
|
-
break;
|
|
399
|
-
case "bottom":
|
|
400
|
-
targetPoint = { x: clickPoint.x, y: bottom };
|
|
401
|
-
break;
|
|
402
|
-
case "left":
|
|
403
|
-
targetPoint = { x: left, y: clickPoint.y };
|
|
404
|
-
break;
|
|
405
|
-
case "right":
|
|
406
|
-
targetPoint = { x: right, y: clickPoint.y };
|
|
407
|
-
break;
|
|
408
|
-
default:
|
|
409
|
-
targetPoint = { x: x + width / 2, y: y + height / 2 };
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
*/
|
|
413
|
-
|
|
414
|
-
// 计算路径点 - 直接返回两点连线,保留转折逻辑作为注释
|
|
415
|
-
|
|
416
|
-
// 检查是否已存在相同源和目标的边,以及反向连接的边,为新边添加偏移以避免重合
|
|
455
|
+
// 检查是否已存在相同源和目标的边,以及反向连接的边
|
|
417
456
|
const existingEdges = shapes.filter(
|
|
418
457
|
shape => shape.shapeType === 'edge' &&
|
|
419
458
|
((shape.sourceId === sourceShape?.id && shape.targetId === targetShape.id) ||
|
|
420
459
|
(shape.sourceId === targetShape.id && shape.targetId === sourceShape?.id))
|
|
421
460
|
);
|
|
422
|
-
|
|
423
|
-
// 计算连接方向
|
|
424
|
-
const dx = targetCenter.x - sourceCenter.x;
|
|
425
|
-
const dy = targetCenter.y - sourceCenter.y;
|
|
426
|
-
|
|
427
|
-
// 为新连线添加偏移量,避免与已存在的连线重叠
|
|
428
|
-
let adjustedStartPoint = { ...startPoint };
|
|
429
|
-
let adjustedEndPoint = { ...targetPoint };
|
|
430
|
-
|
|
431
|
-
if (existingEdges.length > 0) {
|
|
432
|
-
// 新连线的索引(从0开始)
|
|
433
|
-
const index = existingEdges.length;
|
|
434
|
-
|
|
435
|
-
// 生成基于索引的偏移量
|
|
436
|
-
const offsetDistance = 5 * (index + 1);
|
|
437
|
-
|
|
438
|
-
// 根据方向计算偏移方向
|
|
439
|
-
let offsetX = 0, offsetY = 0;
|
|
440
|
-
if (Math.abs(dx) > Math.abs(dy)) {
|
|
441
|
-
// 水平方向为主,垂直偏移
|
|
442
|
-
offsetY = offsetDistance;
|
|
443
|
-
} else {
|
|
444
|
-
// 垂直方向为主,水平偏移
|
|
445
|
-
offsetX = offsetDistance;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
// 确保线条交替偏移方向,避免全部偏向一侧
|
|
449
|
-
if (index % 2 === 1) {
|
|
450
|
-
offsetX = -offsetX;
|
|
451
|
-
offsetY = -offsetY;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
// 应用偏移量到连接点
|
|
455
|
-
adjustedStartPoint = { x: startPoint.x + offsetX, y: startPoint.y + offsetY };
|
|
456
|
-
adjustedEndPoint = { x: targetPoint.x + offsetX, y: targetPoint.y + offsetY };
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
// 使用调整后的点作为waypoints
|
|
460
|
-
const waypoints = [adjustedStartPoint, adjustedEndPoint];
|
|
461
|
-
|
|
462
|
-
/* 保留转折逻辑以备后续使用
|
|
463
|
-
const deltaX = Math.abs(endPoint.x - startPoint.x);
|
|
464
|
-
const deltaY = Math.abs(endPoint.y - startPoint.y);
|
|
465
|
-
|
|
466
|
-
// 计算偏移量,每条现有边增加15px的偏移
|
|
467
|
-
const offsetAmount = existingEdges.length * 15;
|
|
468
|
-
|
|
469
|
-
waypoints = [startPoint];
|
|
470
|
-
if (deltaX > 0 || deltaY > 0) {
|
|
471
|
-
let midPoint;
|
|
472
|
-
|
|
473
|
-
// 如果有现有边,使用偏移的路径以避免重合
|
|
474
|
-
if (existingEdges.length > 0) {
|
|
475
|
-
// 根据连接方向决定偏移方向
|
|
476
|
-
if (deltaX <= deltaY) {
|
|
477
|
-
// 垂直方向为主,水平偏移
|
|
478
|
-
const offsetDir = existingEdges.length % 2 === 0 ? 1 : -1; // 交替偏移方向
|
|
479
|
-
midPoint = {
|
|
480
|
-
x: endPoint.x + offsetDir * offsetAmount,
|
|
481
|
-
y: startPoint.y
|
|
482
|
-
};
|
|
483
|
-
} else {
|
|
484
|
-
// 水平方向为主,垂直偏移
|
|
485
|
-
const offsetDir = existingEdges.length % 2 === 0 ? 1 : -1; // 交替偏移方向
|
|
486
|
-
midPoint = {
|
|
487
|
-
x: startPoint.x,
|
|
488
|
-
y: endPoint.y + offsetDir * offsetAmount
|
|
489
|
-
};
|
|
490
|
-
}
|
|
491
|
-
} else {
|
|
492
|
-
// 没有现有边,使用标准直角路径
|
|
493
|
-
midPoint = deltaX <= deltaY
|
|
494
|
-
? { x: endPoint.x, y: startPoint.y }
|
|
495
|
-
: { x: startPoint.x, y: endPoint.y };
|
|
496
|
-
}
|
|
497
461
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
462
|
+
// groupIndex 用来区分同一对图元之间的多条边,自环也复用这一层偏移。
|
|
463
|
+
const groupIndex = existingEdges.length;
|
|
464
|
+
const { sourcePoint, targetPoint, waypoints } = this.buildEdgeWaypoints(
|
|
465
|
+
sourceShape.bounds,
|
|
466
|
+
targetShape.bounds,
|
|
467
|
+
groupIndex,
|
|
468
|
+
sourceShape.id === targetShape.id
|
|
469
|
+
);
|
|
506
470
|
|
|
507
471
|
return {
|
|
508
472
|
sourceId: sourceShape?.id,
|
|
509
473
|
sourceModelId: sourceShape?.modelId,
|
|
510
474
|
targetId: targetShape.id,
|
|
511
475
|
targetModelId: targetShape.modelId,
|
|
512
|
-
sourcePoint
|
|
513
|
-
targetPoint
|
|
476
|
+
sourcePoint,
|
|
477
|
+
targetPoint,
|
|
514
478
|
waypoints,
|
|
515
479
|
};
|
|
516
480
|
}
|
|
517
481
|
|
|
482
|
+
/**
|
|
483
|
+
* 完成连接操作,计算最终连接点(异步版本,使用 Web Worker)
|
|
484
|
+
*/
|
|
485
|
+
static async completeConnectionAsync(
|
|
486
|
+
sourceShape: Shape | undefined,
|
|
487
|
+
targetShape: Shape,
|
|
488
|
+
clickPoint: { x: number; y: number },
|
|
489
|
+
currentConnectPoint: { x: number; y: number },
|
|
490
|
+
shapes: Shape[] = []
|
|
491
|
+
): Promise<any> {
|
|
492
|
+
try {
|
|
493
|
+
return await workerManager.completeConnection(
|
|
494
|
+
sourceShape,
|
|
495
|
+
targetShape,
|
|
496
|
+
clickPoint,
|
|
497
|
+
currentConnectPoint,
|
|
498
|
+
shapes
|
|
499
|
+
);
|
|
500
|
+
} catch (error) {
|
|
501
|
+
console.error('Error in completeConnectionAsync:', error);
|
|
502
|
+
// 回退到同步版本
|
|
503
|
+
return this.completeConnection(sourceShape, targetShape, clickPoint, currentConnectPoint, shapes);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
518
507
|
/**
|
|
519
508
|
* 计算线路径点
|
|
520
509
|
* 当前实现:直接返回两点连线,暂时不添加转折点
|
|
@@ -582,7 +571,7 @@ export class EdgeUtils {
|
|
|
582
571
|
if (!sourceShape?.bounds) return null;
|
|
583
572
|
|
|
584
573
|
// 如果提供了鼠标位置,使用findNearestConnectPoint计算初始连接点
|
|
585
|
-
if (initialMousePos
|
|
574
|
+
if (initialMousePos) {
|
|
586
575
|
// 直接使用传入的鼠标位置(屏幕坐标)调用findNearestConnectPoint
|
|
587
576
|
// findNearestConnectPoint方法内部会进行坐标转换
|
|
588
577
|
const nearestPoint = this.findNearestConnectPoint(initialMousePos, sourceShape, diagramBounds);
|
|
@@ -655,20 +644,24 @@ export class EdgeUtils {
|
|
|
655
644
|
}
|
|
656
645
|
|
|
657
646
|
/**
|
|
658
|
-
*
|
|
647
|
+
* 初始化所有连线的端点(同步版本)
|
|
659
648
|
* 用于在初始加载后端数据后,自动计算所有连线的合适端点,避免线横跨图元
|
|
660
649
|
* @param shapes 所有图元列表
|
|
661
650
|
* @param updateShape 更新图元的回调函数
|
|
651
|
+
* @param shapeMapIndex 可选,id → Shape 的索引(来自 graphStore.shapeMap)
|
|
662
652
|
*/
|
|
663
|
-
static initializeAllEdgeEndpoints(shapes: Shape[], updateShape: (shape: Shape) => void) {
|
|
653
|
+
static initializeAllEdgeEndpoints(shapes: Shape[], updateShape: (shape: Shape) => void, shapeMapIndex?: Map<string, Shape>) {
|
|
664
654
|
const edges = shapes.filter((shape) => shape.shapeType === "edge");
|
|
665
655
|
|
|
666
|
-
|
|
656
|
+
const findShape = shapeMapIndex
|
|
657
|
+
? (id: string) => shapeMapIndex.get(id) ?? null
|
|
658
|
+
: (id: string) => shapes.find(s => s.id === id) ?? null
|
|
659
|
+
|
|
660
|
+
// 按源-目标对分组
|
|
667
661
|
const edgeGroups = new Map<string, Shape[]>();
|
|
668
662
|
|
|
669
663
|
edges.forEach((edge) => {
|
|
670
664
|
if (edge.sourceId && edge.targetId) {
|
|
671
|
-
// 创建源-目标对的规范化键(确保 A-B 和 B-A 使用相同的键)
|
|
672
665
|
const isForward = edge.sourceId.localeCompare(edge.targetId) <= 0;
|
|
673
666
|
const groupKey = isForward
|
|
674
667
|
? `${edge.sourceId}-${edge.targetId}`
|
|
@@ -681,133 +674,57 @@ export class EdgeUtils {
|
|
|
681
674
|
}
|
|
682
675
|
});
|
|
683
676
|
|
|
684
|
-
//
|
|
685
|
-
edgeGroups.forEach((groupEdges
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
const sourceShape = shapes.find((s) => s.id === edge.sourceId);
|
|
690
|
-
const targetShape = shapes.find((s) => s.id === edge.targetId);
|
|
691
|
-
|
|
692
|
-
if (sourceShape && targetShape && sourceShape.bounds && targetShape.bounds) {
|
|
693
|
-
// 计算基本连接点
|
|
694
|
-
const { x: sx = 0, y: sy = 0, width: sw = 0, height: sh = 0 } = sourceShape.bounds;
|
|
695
|
-
const { x: tx = 0, y: ty = 0, width: tw = 0, height: th = 0 } = targetShape.bounds;
|
|
696
|
-
|
|
697
|
-
// 计算中心点
|
|
698
|
-
const sourceCenter = { x: sx + sw / 2, y: sy + sh / 2 };
|
|
699
|
-
const targetCenter = { x: tx + tw / 2, y: ty + th / 2 };
|
|
700
|
-
|
|
701
|
-
// 计算连接方向
|
|
702
|
-
const dx = targetCenter.x - sourceCenter.x;
|
|
703
|
-
const dy = targetCenter.y - sourceCenter.y;
|
|
704
|
-
|
|
705
|
-
// 生成基于索引的偏移量(小到不会明显影响,但足以分开线条)
|
|
706
|
-
const offsetDistance = 5 * (index + 1);
|
|
707
|
-
|
|
708
|
-
// 根据方向计算偏移方向
|
|
709
|
-
let offsetX = 0, offsetY = 0;
|
|
710
|
-
if (Math.abs(dx) > Math.abs(dy)) {
|
|
711
|
-
// 水平方向为主,垂直偏移
|
|
712
|
-
offsetY = offsetDistance;
|
|
713
|
-
} else {
|
|
714
|
-
// 垂直方向为主,水平偏移
|
|
715
|
-
offsetX = offsetDistance;
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
// 确保线条交替偏移方向,避免全部偏向一侧
|
|
719
|
-
if (index % 2 === 1) {
|
|
720
|
-
offsetX = -offsetX;
|
|
721
|
-
offsetY = -offsetY;
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
// 确定连接点,添加偏移
|
|
725
|
-
let sourcePoint, targetPoint;
|
|
726
|
-
|
|
727
|
-
if (Math.abs(dx) > Math.abs(dy)) {
|
|
728
|
-
// 水平方向
|
|
729
|
-
sourcePoint = dx > 0
|
|
730
|
-
? { x: sx + sw, y: sourceCenter.y + offsetY }
|
|
731
|
-
: { x: sx, y: sourceCenter.y + offsetY };
|
|
732
|
-
|
|
733
|
-
targetPoint = dx > 0
|
|
734
|
-
? { x: tx, y: targetCenter.y + offsetY }
|
|
735
|
-
: { x: tx + tw, y: targetCenter.y + offsetY };
|
|
736
|
-
} else {
|
|
737
|
-
// 垂直方向
|
|
738
|
-
sourcePoint = dy > 0
|
|
739
|
-
? { x: sourceCenter.x + offsetX, y: sy + sh }
|
|
740
|
-
: { x: sourceCenter.x + offsetX, y: sy };
|
|
741
|
-
|
|
742
|
-
targetPoint = dy > 0
|
|
743
|
-
? { x: targetCenter.x + offsetX, y: ty }
|
|
744
|
-
: { x: targetCenter.x + offsetX, y: ty + th };
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
// 更新连线,只使用源点和目标点确保线条保持直线
|
|
748
|
-
const waypoints = [sourcePoint, targetPoint];
|
|
749
|
-
|
|
750
|
-
const updatedEdge = {
|
|
751
|
-
...edge,
|
|
752
|
-
waypointId: JSON.stringify(waypoints),
|
|
753
|
-
};
|
|
754
|
-
|
|
755
|
-
updateShape(updatedEdge);
|
|
756
|
-
}
|
|
757
|
-
});
|
|
758
|
-
} else {
|
|
759
|
-
// 单线条情况
|
|
760
|
-
const edge = groupEdges[0];
|
|
761
|
-
const sourceShape = shapes.find((s) => s.id === edge.sourceId);
|
|
762
|
-
const targetShape = shapes.find((s) => s.id === edge.targetId);
|
|
677
|
+
// 处理每个分组,使用 calcBestEndpoints 共用算法
|
|
678
|
+
edgeGroups.forEach((groupEdges) => {
|
|
679
|
+
groupEdges.forEach((edge, index) => {
|
|
680
|
+
const sourceShape = edge.sourceId ? findShape(edge.sourceId) : null;
|
|
681
|
+
const targetShape = edge.targetId ? findShape(edge.targetId) : null;
|
|
763
682
|
|
|
764
683
|
if (sourceShape && targetShape && sourceShape.bounds && targetShape.bounds) {
|
|
765
|
-
const
|
|
766
|
-
const {
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
// 计算连接方向
|
|
773
|
-
const dx = targetCenter.x - sourceCenter.x;
|
|
774
|
-
const dy = targetCenter.y - sourceCenter.y;
|
|
775
|
-
|
|
776
|
-
// 确定连接点
|
|
777
|
-
let sourcePoint, targetPoint;
|
|
778
|
-
|
|
779
|
-
if (Math.abs(dx) > Math.abs(dy)) {
|
|
780
|
-
// 水平方向
|
|
781
|
-
sourcePoint = dx > 0
|
|
782
|
-
? { x: sx + sw, y: sourceCenter.y }
|
|
783
|
-
: { x: sx, y: sourceCenter.y };
|
|
784
|
-
|
|
785
|
-
targetPoint = dx > 0
|
|
786
|
-
? { x: tx, y: targetCenter.y }
|
|
787
|
-
: { x: tx + tw, y: targetCenter.y };
|
|
788
|
-
} else {
|
|
789
|
-
// 垂直方向
|
|
790
|
-
sourcePoint = dy > 0
|
|
791
|
-
? { x: sourceCenter.x, y: sy + sh }
|
|
792
|
-
: { x: sourceCenter.x, y: sy };
|
|
793
|
-
|
|
794
|
-
targetPoint = dy > 0
|
|
795
|
-
? { x: targetCenter.x, y: ty }
|
|
796
|
-
: { x: targetCenter.x, y: ty + th };
|
|
797
|
-
}
|
|
684
|
+
const groupIndex = groupEdges.length > 1 ? index : 0;
|
|
685
|
+
const { waypoints } = this.buildEdgeWaypoints(
|
|
686
|
+
sourceShape.bounds,
|
|
687
|
+
targetShape.bounds,
|
|
688
|
+
groupIndex,
|
|
689
|
+
sourceShape.id === targetShape.id
|
|
690
|
+
);
|
|
798
691
|
|
|
799
|
-
// 更新连线
|
|
800
692
|
const updatedEdge = {
|
|
801
693
|
...edge,
|
|
802
|
-
waypointId: JSON.stringify(
|
|
694
|
+
waypointId: JSON.stringify(waypoints),
|
|
803
695
|
};
|
|
804
696
|
|
|
805
697
|
updateShape(updatedEdge);
|
|
806
698
|
}
|
|
807
|
-
}
|
|
699
|
+
});
|
|
808
700
|
});
|
|
809
701
|
}
|
|
810
702
|
|
|
703
|
+
/**
|
|
704
|
+
* 初始化所有连线的端点(异步版本,使用 Web Worker)
|
|
705
|
+
* 用于在初始加载后端数据后,自动计算所有连线的合适端点,避免线横跨图元
|
|
706
|
+
* @param shapes 所有图元列表
|
|
707
|
+
* @param updateShape 更新图元的回调函数
|
|
708
|
+
* @param shapeMapIndex 可选,id → Shape 的索引(来自 graphStore.shapeMap)
|
|
709
|
+
*/
|
|
710
|
+
static async initializeAllEdgeEndpointsAsync(shapes: Shape[], updateShape: (shape: Shape) => void, shapeMapIndex?: Map<string, Shape>): Promise<void> {
|
|
711
|
+
try {
|
|
712
|
+
const updatedEdges = await workerManager.initializeAllEdgeEndpoints(
|
|
713
|
+
shapes,
|
|
714
|
+
shapeMapIndex
|
|
715
|
+
);
|
|
716
|
+
|
|
717
|
+
// 更新所有返回的边缘
|
|
718
|
+
updatedEdges.forEach(edge => {
|
|
719
|
+
updateShape(edge);
|
|
720
|
+
});
|
|
721
|
+
} catch (error) {
|
|
722
|
+
console.error('Error in initializeAllEdgeEndpointsAsync:', error);
|
|
723
|
+
// 回退到同步版本
|
|
724
|
+
this.initializeAllEdgeEndpoints(shapes, updateShape, shapeMapIndex);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
|
|
811
728
|
/**
|
|
812
729
|
* 根据 pin 的方向和位置计算连接点
|
|
813
730
|
* 连接点位于 pin 的外侧边缘(远离父图元的一侧):
|