|
@@ -2,6 +2,7 @@ import { StructureType, MindmapConnectorType, TopicType } from "@/enum";
|
|
|
import { TopicItem } from "@/types";
|
|
|
import { Edge, Graph, Path } from "@antv/x6";
|
|
|
import { getTheme } from "./theme";
|
|
|
+import { caclculateX } from "@/utils/hierarchy/rightFishbone";
|
|
|
|
|
|
// 曲线
|
|
|
Graph.registerConnector(
|
|
@@ -199,9 +200,7 @@ Graph.registerConnector(
|
|
|
Graph.registerConnector(
|
|
|
"bracket-branch-connector",
|
|
|
function (sourcePoint, targetPoint, routerPoints, options) {
|
|
|
- const midX =
|
|
|
- sourcePoint.x +
|
|
|
- (sourcePoint.x < targetPoint.x ? 20 : -20);
|
|
|
+ const midX = sourcePoint.x + (sourcePoint.x < targetPoint.x ? 20 : -20);
|
|
|
const midY = sourcePoint.y;
|
|
|
const pathData = `
|
|
|
M ${sourcePoint.x} ${sourcePoint.y}
|
|
@@ -216,9 +215,7 @@ Graph.registerConnector(
|
|
|
Graph.registerConnector(
|
|
|
"bracket-sub-connector",
|
|
|
function (sourcePoint, targetPoint, routerPoints, options) {
|
|
|
- const midX =
|
|
|
- sourcePoint.x +
|
|
|
- (sourcePoint.x < targetPoint.x ? 10 : -10);
|
|
|
+ const midX = sourcePoint.x + (sourcePoint.x < targetPoint.x ? 10 : -10);
|
|
|
const midY = sourcePoint.y;
|
|
|
const pathData = `
|
|
|
M ${sourcePoint.x} ${sourcePoint.y}
|
|
@@ -231,21 +228,274 @@ Graph.registerConnector(
|
|
|
true
|
|
|
);
|
|
|
|
|
|
+// 一个子项的括号
|
|
|
+Graph.registerConnector(
|
|
|
+ "bracket-one-branch-connector",
|
|
|
+ function (sourcePoint, targetPoint, routerPoints, options, edgeView) {
|
|
|
+ const targetCell = edgeView.targetView?.cell;
|
|
|
+ let height = 0;
|
|
|
+ if (targetCell?.isNode()) {
|
|
|
+ height = targetCell.getBBox().height;
|
|
|
+ }
|
|
|
+ const targetTop = targetPoint.y - height / 2 - 3;
|
|
|
+ const targetBottom = targetPoint.y + height / 2 + 3;
|
|
|
+ const offset = 10;
|
|
|
+ const midX =
|
|
|
+ sourcePoint.x + (sourcePoint.x < targetPoint.x ? offset : -offset);
|
|
|
+ const midY = sourcePoint.y;
|
|
|
+ const pathData = `
|
|
|
+ M ${sourcePoint.x} ${sourcePoint.y}
|
|
|
+ Q ${midX} ${midY} ${midX} ${sourcePoint.y - offset}
|
|
|
+ L ${midX} ${targetTop + offset}
|
|
|
+ Q ${midX} ${targetTop} ${midX + offset} ${targetTop}
|
|
|
+ M ${sourcePoint.x} ${sourcePoint.y}
|
|
|
+ Q ${midX} ${midY} ${midX} ${sourcePoint.y + offset}
|
|
|
+ L ${midX} ${targetBottom - offset}
|
|
|
+ Q ${midX} ${targetBottom} ${midX + offset} ${targetBottom}
|
|
|
+ `;
|
|
|
+ return options.raw ? Path.parse(pathData) : pathData;
|
|
|
+ },
|
|
|
+ true
|
|
|
+);
|
|
|
+Graph.registerConnector(
|
|
|
+ "bracket-one-sub-connector",
|
|
|
+ function (sourcePoint, targetPoint, routerPoints, options, edgeView) {
|
|
|
+ const targetCell = edgeView.targetView?.cell;
|
|
|
+ let height = 0;
|
|
|
+ if (targetCell?.isNode()) {
|
|
|
+ height = targetCell.getBBox().height;
|
|
|
+ }
|
|
|
+ const targetTop = targetPoint.y - height / 2 + 3;
|
|
|
+ const targetBottom = targetPoint.y + height / 2 - 3;
|
|
|
+ const offset = 5;
|
|
|
+ const midX =
|
|
|
+ sourcePoint.x + (sourcePoint.x < targetPoint.x ? offset : -offset);
|
|
|
+ const midY = sourcePoint.y;
|
|
|
+ const pathData = `
|
|
|
+ M ${sourcePoint.x} ${sourcePoint.y}
|
|
|
+ Q ${midX} ${midY} ${midX} ${sourcePoint.y - offset}
|
|
|
+ L ${midX} ${targetTop + offset}
|
|
|
+ Q ${midX} ${targetTop} ${midX + offset} ${targetTop}
|
|
|
+ M ${sourcePoint.x} ${sourcePoint.y}
|
|
|
+ Q ${midX} ${midY} ${midX} ${sourcePoint.y + offset}
|
|
|
+ L ${midX} ${targetBottom - offset}
|
|
|
+ Q ${midX} ${targetBottom} ${midX + offset} ${targetBottom}
|
|
|
+ `;
|
|
|
+ return options.raw ? Path.parse(pathData) : pathData;
|
|
|
+ },
|
|
|
+ true
|
|
|
+);
|
|
|
+
|
|
|
+// 树形图
|
|
|
+Graph.registerConnector(
|
|
|
+ "tree-shape-connector",
|
|
|
+ function (sourcePoint, targetPoint, routerPoints, options) {
|
|
|
+ const pathData = `
|
|
|
+ M ${sourcePoint.x} ${sourcePoint.y}
|
|
|
+ L ${sourcePoint.x} ${targetPoint.y}
|
|
|
+ L ${targetPoint.x} ${targetPoint.y}
|
|
|
+ `;
|
|
|
+ return options.raw ? Path.parse(pathData) : pathData;
|
|
|
+ },
|
|
|
+ true
|
|
|
+);
|
|
|
+
|
|
|
+// 右侧鱼骨图
|
|
|
+Graph.registerConnector(
|
|
|
+ "fishbone-branch-right-connector",
|
|
|
+ function (sourcePoint, targetPoint, routerPoints, options, edgeView) {
|
|
|
+ const direction = sourcePoint.y > targetPoint.y ? "up" : "down";
|
|
|
+ const node = edgeView.targetView?.cell;
|
|
|
+ let targetY = targetPoint.y;
|
|
|
+ if (node?.isNode() && direction === "down") {
|
|
|
+ targetY -= node.size().height;
|
|
|
+ }
|
|
|
+ const midX = caclculateX({ x: targetPoint.x, y: targetY }, sourcePoint.y, "right", direction);
|
|
|
+ let pathData = "";
|
|
|
+ if (direction === "up") {
|
|
|
+ pathData = `
|
|
|
+ M ${targetPoint.x} ${targetPoint.y}
|
|
|
+ L ${midX} ${sourcePoint.y}
|
|
|
+ L ${sourcePoint.x} ${sourcePoint.y}
|
|
|
+ `;
|
|
|
+ } else {
|
|
|
+ pathData = `
|
|
|
+ M ${targetPoint.x} ${targetY}
|
|
|
+ L ${midX} ${sourcePoint.y}
|
|
|
+ L ${sourcePoint.x} ${sourcePoint.y}
|
|
|
+ `;
|
|
|
+ }
|
|
|
+
|
|
|
+ return options.raw ? Path.parse(pathData) : pathData;
|
|
|
+ },
|
|
|
+ true
|
|
|
+);
|
|
|
+Graph.registerConnector(
|
|
|
+ "fishbone-sub-right-connector",
|
|
|
+ function (sourcePoint, targetPoint, routerPoints, options, edgeView) {
|
|
|
+ const sourceNode = edgeView.sourceView?.cell;
|
|
|
+ const direction = sourcePoint.y < targetPoint.y ? "up" : "down";
|
|
|
+ let midX = caclculateX(sourcePoint, targetPoint.y, "right", direction);
|
|
|
+ if (direction === "down" && sourceNode?.isNode()) {
|
|
|
+ midX = caclculateX(
|
|
|
+ { x: sourcePoint.x, y: sourcePoint.y - sourceNode.size().height },
|
|
|
+ targetPoint.y,
|
|
|
+ "right",
|
|
|
+ direction
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ let pathData = "";
|
|
|
+ if (sourceNode?.isNode() && sourceNode.data.type === TopicType.sub) {
|
|
|
+ const size = sourceNode.size();
|
|
|
+ const sourceP = {
|
|
|
+ x: sourcePoint.x + size.width / 2,
|
|
|
+ y: sourcePoint.y - size.height / 2,
|
|
|
+ };
|
|
|
+ pathData = `
|
|
|
+ M ${sourceP.x} ${sourceP.y}
|
|
|
+ L ${sourceP.x + 10} ${sourceP.y}
|
|
|
+ L ${sourceP.x + 10} ${targetPoint.y}
|
|
|
+ L ${targetPoint.x} ${targetPoint.y}
|
|
|
+ `;
|
|
|
+ } else {
|
|
|
+ pathData = `
|
|
|
+ M ${midX} ${targetPoint.y}
|
|
|
+ L ${targetPoint.x} ${targetPoint.y}
|
|
|
+ `;
|
|
|
+ }
|
|
|
+ return options.raw ? Path.parse(pathData) : pathData;
|
|
|
+ },
|
|
|
+ true
|
|
|
+);
|
|
|
+
|
|
|
+// 左侧鱼骨图
|
|
|
+Graph.registerConnector(
|
|
|
+ "fishbone-branch-left-connector",
|
|
|
+ function (sourcePoint, targetPoint, routerPoints, options, edgeView) {
|
|
|
+ const direction = sourcePoint.y > targetPoint.y ? "up" : "down";
|
|
|
+ const node = edgeView.targetView?.cell;
|
|
|
+ let targetY = targetPoint.y;
|
|
|
+ if (node?.isNode() && direction === "down") {
|
|
|
+ targetY -= node.size().height;
|
|
|
+ }
|
|
|
+ const midX = caclculateX({ x: targetPoint.x, y: targetY }, sourcePoint.y, "left", direction);
|
|
|
+ let pathData = "";
|
|
|
+ if (direction === "up") {
|
|
|
+ pathData = `
|
|
|
+ M ${targetPoint.x} ${targetPoint.y}
|
|
|
+ L ${midX} ${sourcePoint.y}
|
|
|
+ L ${sourcePoint.x} ${sourcePoint.y}
|
|
|
+ `;
|
|
|
+ } else {
|
|
|
+ pathData = `
|
|
|
+ M ${targetPoint.x} ${targetY}
|
|
|
+ L ${midX} ${sourcePoint.y}
|
|
|
+ L ${sourcePoint.x} ${sourcePoint.y}
|
|
|
+ `;
|
|
|
+ }
|
|
|
+
|
|
|
+ return options.raw ? Path.parse(pathData) : pathData;
|
|
|
+ },
|
|
|
+ true
|
|
|
+);
|
|
|
+Graph.registerConnector(
|
|
|
+ "fishbone-sub-left-connector",
|
|
|
+ function (sourcePoint, targetPoint, routerPoints, options, edgeView) {
|
|
|
+ const sourceNode = edgeView.sourceView?.cell;
|
|
|
+
|
|
|
+ let pathData = "";
|
|
|
+ // 子主题到子主题
|
|
|
+ if (sourceNode?.isNode() && sourceNode.data.type === TopicType.sub) {
|
|
|
+ const size = sourceNode.size();
|
|
|
+ const sourceP = {
|
|
|
+ x: sourcePoint.x - size.width,
|
|
|
+ y: sourcePoint.y,
|
|
|
+ };
|
|
|
+ pathData = `
|
|
|
+ M ${sourceP.x} ${sourceP.y}
|
|
|
+ L ${sourceP.x - 10} ${sourceP.y}
|
|
|
+ L ${sourceP.x - 10} ${targetPoint.y}
|
|
|
+ L ${targetPoint.x} ${targetPoint.y}
|
|
|
+ `;
|
|
|
+ } else {
|
|
|
+ // 分支子主题到子主题
|
|
|
+ const direction = sourcePoint.y < targetPoint.y ? "up" : "down";
|
|
|
+ const size = sourceNode?.isNode() ? sourceNode.size() : { width: 0, height: 0};
|
|
|
+ let midX = caclculateX({
|
|
|
+ x: sourcePoint.x - size.width / 2,
|
|
|
+ y: sourcePoint.y + size.height / 2,
|
|
|
+ }, targetPoint.y, "left", direction);
|
|
|
+ if (direction === "down") {
|
|
|
+ midX = caclculateX(
|
|
|
+ {
|
|
|
+ x: sourcePoint.x - size.width / 2,
|
|
|
+ y: sourcePoint.y - size.height / 2,
|
|
|
+ },
|
|
|
+ targetPoint.y,
|
|
|
+ "left",
|
|
|
+ direction
|
|
|
+ );
|
|
|
+ }
|
|
|
+ pathData = `
|
|
|
+ M ${midX} ${targetPoint.y}
|
|
|
+ L ${targetPoint.x} ${targetPoint.y}
|
|
|
+ `;
|
|
|
+ }
|
|
|
+ return options.raw ? Path.parse(pathData) : pathData;
|
|
|
+ },
|
|
|
+ true
|
|
|
+);
|
|
|
const getConnector = (
|
|
|
structure: StructureType,
|
|
|
theme: string,
|
|
|
- type: TopicType
|
|
|
+ type: TopicType,
|
|
|
+ options?: Record<string, any>
|
|
|
) => {
|
|
|
- // TODO根据结构处理连接线
|
|
|
+ // 树状结构图
|
|
|
if (structure === StructureType.tree) {
|
|
|
return `tree-${type}-connector`;
|
|
|
}
|
|
|
+ // 组织结构图
|
|
|
if (structure === StructureType.organization) {
|
|
|
return `organization-${type}-connector`;
|
|
|
}
|
|
|
- if ([StructureType.leftBracket, StructureType.rightBracket].includes(structure)) {
|
|
|
+ // 时间图
|
|
|
+ if (
|
|
|
+ [
|
|
|
+ StructureType.upwardTime,
|
|
|
+ StructureType.downwardTime,
|
|
|
+ StructureType.horizontalTime,
|
|
|
+ ].includes(structure)
|
|
|
+ ) {
|
|
|
+ return `poly-${type}-connector`;
|
|
|
+ }
|
|
|
+ // 括号图
|
|
|
+ if (
|
|
|
+ [StructureType.leftBracket, StructureType.rightBracket].includes(structure)
|
|
|
+ ) {
|
|
|
+ if (options?.onlyOneChild) {
|
|
|
+ return `bracket-one-${type}-connector`;
|
|
|
+ }
|
|
|
return `bracket-${type}-connector`;
|
|
|
}
|
|
|
+ // 树形图
|
|
|
+ if (
|
|
|
+ [
|
|
|
+ StructureType.leftTreeShape,
|
|
|
+ StructureType.rightTreeShape,
|
|
|
+ StructureType.treeShape,
|
|
|
+ ].includes(structure)
|
|
|
+ ) {
|
|
|
+ return `tree-shape-connector`;
|
|
|
+ }
|
|
|
+ // 鱼骨
|
|
|
+ if (structure === StructureType.leftFishbone) {
|
|
|
+ return `fishbone-${type}-left-connector`;
|
|
|
+ }
|
|
|
+ if (structure === StructureType.rightFishbone) {
|
|
|
+ return `fishbone-${type}-right-connector`;
|
|
|
+ }
|
|
|
const themeObj = getTheme(theme);
|
|
|
if (type === TopicType.branch) {
|
|
|
return `${themeObj.branchConnector}-${type}-connector`;
|
|
@@ -254,7 +504,11 @@ const getConnector = (
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-const getSourceAnchor = (type: TopicType, structure: StructureType) => {
|
|
|
+const getSourceAnchor = (
|
|
|
+ type: TopicType,
|
|
|
+ structure: StructureType,
|
|
|
+ options?: Record<string, any>
|
|
|
+) => {
|
|
|
switch (structure) {
|
|
|
case StructureType.left: {
|
|
|
return type === TopicType.branch
|
|
@@ -312,20 +566,38 @@ const getSourceAnchor = (type: TopicType, structure: StructureType) => {
|
|
|
},
|
|
|
};
|
|
|
}
|
|
|
- case StructureType.leftFishbone:
|
|
|
- case StructureType.leftTreeShape:
|
|
|
- case StructureType.rightFishbone:
|
|
|
- case StructureType.rightTreeShape:
|
|
|
+ case StructureType.upwardTime:
|
|
|
+ case StructureType.downwardTime:
|
|
|
+ case StructureType.horizontalTime: {
|
|
|
return {
|
|
|
name: "center",
|
|
|
};
|
|
|
+ }
|
|
|
+ case StructureType.leftFishbone: {
|
|
|
+ return {
|
|
|
+ name: type === TopicType.branch ? "left" : "right",
|
|
|
+ };
|
|
|
+ }
|
|
|
+ case StructureType.rightFishbone:
|
|
|
+ return {
|
|
|
+ name: type === TopicType.branch ? "right" : "bottom",
|
|
|
+ };
|
|
|
+ case StructureType.leftTreeShape:
|
|
|
+ case StructureType.rightTreeShape:
|
|
|
+ case StructureType.treeShape: {
|
|
|
+ return "bottom";
|
|
|
+ }
|
|
|
}
|
|
|
return {
|
|
|
name: "center",
|
|
|
};
|
|
|
};
|
|
|
|
|
|
-const getTargetAnchor = (type: TopicType, structure: StructureType) => {
|
|
|
+const getTargetAnchor = (
|
|
|
+ type: TopicType,
|
|
|
+ structure: StructureType,
|
|
|
+ options?: Record<string, any>
|
|
|
+) => {
|
|
|
switch (structure) {
|
|
|
case StructureType.left: {
|
|
|
return {
|
|
@@ -367,16 +639,27 @@ const getTargetAnchor = (type: TopicType, structure: StructureType) => {
|
|
|
},
|
|
|
};
|
|
|
}
|
|
|
- case StructureType.leftFishbone:
|
|
|
- case StructureType.leftTreeShape:
|
|
|
+ case StructureType.upwardTime:
|
|
|
+ case StructureType.downwardTime:
|
|
|
+ case StructureType.horizontalTime: {
|
|
|
+ return {
|
|
|
+ name: "left",
|
|
|
+ };
|
|
|
+ }
|
|
|
+ case StructureType.leftFishbone: {
|
|
|
+ return {
|
|
|
+ name: type === TopicType.branch ? "bottom" : "right",
|
|
|
+ };
|
|
|
+ }
|
|
|
case StructureType.rightFishbone:
|
|
|
- case StructureType.rightTreeShape:
|
|
|
return {
|
|
|
- name: "center",
|
|
|
- args: {
|
|
|
- dx: "25%",
|
|
|
- },
|
|
|
+ name: type === TopicType.branch ? "bottom" : "left",
|
|
|
};
|
|
|
+ case StructureType.leftTreeShape:
|
|
|
+ case StructureType.rightTreeShape:
|
|
|
+ case StructureType.treeShape: {
|
|
|
+ return "left";
|
|
|
+ }
|
|
|
}
|
|
|
return {
|
|
|
name: "center",
|
|
@@ -400,22 +683,23 @@ export const createEdge = (
|
|
|
sourceId: string,
|
|
|
item: { id: string; data: TopicItem },
|
|
|
structure: StructureType,
|
|
|
- theme: string
|
|
|
+ theme: string,
|
|
|
+ options: Record<string, any> = {}
|
|
|
): Edge => {
|
|
|
return graph.createEdge({
|
|
|
id: item.id + "-edge",
|
|
|
inherit: "edge",
|
|
|
connector: {
|
|
|
- name: getConnector(structure, theme, item.data.type),
|
|
|
+ name: getConnector(structure, theme, item.data.type, options),
|
|
|
},
|
|
|
zIndex: 0,
|
|
|
source: {
|
|
|
cell: sourceId,
|
|
|
- anchor: getSourceAnchor(item.data.type, structure),
|
|
|
+ anchor: getSourceAnchor(item.data.type, structure, options),
|
|
|
},
|
|
|
target: {
|
|
|
cell: item.id,
|
|
|
- anchor: getTargetAnchor(item.data.type, structure),
|
|
|
+ anchor: getTargetAnchor(item.data.type, structure, options),
|
|
|
},
|
|
|
attrs: {
|
|
|
line: {
|