123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743 |
- 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(
- "curve-branch-connector",
- (sourcePoint, targetPoint, routerPoints, options) => {
- const midX = sourcePoint.x;
- const ctrX = (targetPoint.x - midX) / 5 + midX;
- const ctrY = targetPoint.y;
- const pathData = `
- M ${sourcePoint.x} ${sourcePoint.y}
- Q ${ctrX} ${ctrY} ${targetPoint.x} ${targetPoint.y}
- `;
- return options.raw ? Path.parse(pathData) : pathData;
- },
- true
- );
- Graph.registerConnector(
- "curve-sub-connector",
- (sourcePoint, targetPoint, routerPoints, options) => {
- const midX = sourcePoint.x + (sourcePoint.x < targetPoint.x ? 10 : -10);
- const midY = sourcePoint.y;
- const ctrX = (targetPoint.x - midX) / 5 + midX;
- const ctrY = targetPoint.y;
- const pathData = `
- M ${sourcePoint.x} ${sourcePoint.y}
- L ${midX} ${midY}
- Q ${ctrX} ${ctrY} ${targetPoint.x} ${targetPoint.y}
- `;
- return options.raw ? Path.parse(pathData) : pathData;
- },
- true
- );
- // 直线
- Graph.registerConnector(
- "straight-branch-connector",
- function (sourcePoint, targetPoint, routerPoints, options) {
- const halfWidth = this.sourceBBox.width / 2;
- const midX =
- sourcePoint.x +
- (sourcePoint.x < targetPoint.x ? halfWidth + 10 : -halfWidth - 10);
- const midY = sourcePoint.y;
- const pathData = `
- M ${sourcePoint.x} ${sourcePoint.y}
- L ${midX} ${midY}
- L ${targetPoint.x} ${targetPoint.y}
- `;
- return options.raw ? Path.parse(pathData) : pathData;
- },
- true
- );
- Graph.registerConnector(
- "straight-sub-connector",
- function (sourcePoint, targetPoint, routerPoints, options) {
- const midX = sourcePoint.x + (sourcePoint.x < targetPoint.x ? 10 : -10);
- const midY = sourcePoint.y;
- const pathData = `
- M ${sourcePoint.x} ${sourcePoint.y}
- L ${midX} ${midY}
- L ${targetPoint.x} ${targetPoint.y}
- `;
- return options.raw ? Path.parse(pathData) : pathData;
- },
- true
- );
- // 圆角折线
- Graph.registerConnector(
- "rounded-branch-connector",
- function (sourcePoint, targetPoint, routerPoints, options) {
- const halfWidth = this.sourceBBox.width / 2;
- const midX =
- sourcePoint.x +
- (sourcePoint.x < targetPoint.x ? halfWidth + 10 : -halfWidth - 10);
- const midY = sourcePoint.y;
- const pathData = `
- M ${sourcePoint.x} ${sourcePoint.y}
- L ${midX} ${midY}
- L ${midX} ${targetPoint.y + (targetPoint.y < sourcePoint.y ? 5 : targetPoint.y === sourcePoint.y ? 0 : -5)}
- Q ${midX} ${targetPoint.y} ${midX + (targetPoint.x < sourcePoint.x ? -5 : 5)} ${targetPoint.y}
- L ${targetPoint.x} ${targetPoint.y}
- `;
- return options.raw ? Path.parse(pathData) : pathData;
- },
- true
- );
- Graph.registerConnector(
- "rounded-sub-connector",
- (sourcePoint, targetPoint, routerPoints, options) => {
- const midX =
- sourcePoint.x < targetPoint.x ? sourcePoint.x + 10 : sourcePoint.x - 10;
- const midY = sourcePoint.y;
- // 可能存在误差
- const deviationY = Math.abs(targetPoint.y - sourcePoint.y);
- const pathData =
- deviationY < 10
- ? `M ${sourcePoint.x} ${sourcePoint.y}
- L ${targetPoint.x} ${targetPoint.y}
- `
- : `
- M ${sourcePoint.x} ${sourcePoint.y}
- L ${midX} ${midY}
- L ${midX} ${targetPoint.y + (targetPoint.y < sourcePoint.y ? 5 : -5)}
- Q ${midX} ${targetPoint.y} ${midX + (targetPoint.x < sourcePoint.x ? -5 : 5)} ${targetPoint.y}
- L ${targetPoint.x} ${targetPoint.y}
- `;
- return options.raw ? Path.parse(pathData) : pathData;
- },
- true
- );
- // 折线
- Graph.registerConnector(
- "poly-branch-connector",
- function (sourcePoint, targetPoint, routerPoints, options) {
- const halfWidth = this.sourceBBox.width / 2;
- const midX =
- sourcePoint.x +
- (sourcePoint.x < targetPoint.x ? halfWidth + 10 : -halfWidth - 10);
- const midY = sourcePoint.y;
- const pathData = `
- M ${sourcePoint.x} ${sourcePoint.y}
- L ${midX} ${midY}
- L ${midX} ${targetPoint.y}
- L ${targetPoint.x} ${targetPoint.y}
- `;
- return options.raw ? Path.parse(pathData) : pathData;
- },
- true
- );
- Graph.registerConnector(
- "poly-sub-connector",
- function (sourcePoint, targetPoint, routerPoints, options) {
- const midX = sourcePoint.x + (sourcePoint.x < targetPoint.x ? 10 : -10);
- const midY = sourcePoint.y;
- const pathData = `
- M ${sourcePoint.x} ${sourcePoint.y}
- L ${midX} ${midY}
- L ${midX} ${targetPoint.y}
- L ${targetPoint.x} ${targetPoint.y}
- `;
- return options.raw ? Path.parse(pathData) : pathData;
- },
- true
- );
- // 树形
- Graph.registerConnector(
- "tree-branch-connector",
- function (sourcePoint, targetPoint, routerPoints, options) {
- const pathData = `
- M ${sourcePoint.x} ${sourcePoint.y}
- L ${sourcePoint.x} ${sourcePoint.y + 10}
- L ${targetPoint.x} ${sourcePoint.y + 10}
- L ${targetPoint.x} ${targetPoint.y}
- `;
- return options.raw ? Path.parse(pathData) : pathData;
- },
- true
- );
- Graph.registerConnector(
- "tree-sub-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(
- "organization-branch-connector",
- function (sourcePoint, targetPoint, routerPoints, options) {
- const pathData = `
- M ${sourcePoint.x} ${sourcePoint.y}
- L ${sourcePoint.x} ${sourcePoint.y + 10}
- L ${targetPoint.x} ${sourcePoint.y + 10}
- L ${targetPoint.x} ${targetPoint.y}
- `;
- return options.raw ? Path.parse(pathData) : pathData;
- },
- true
- );
- Graph.registerConnector(
- "organization-sub-connector",
- function (sourcePoint, targetPoint, routerPoints, options) {
- const pathData = `
- M ${sourcePoint.x} ${sourcePoint.y}
- L ${sourcePoint.x} ${sourcePoint.y + 10}
- L ${targetPoint.x} ${sourcePoint.y + 10}
- L ${targetPoint.x} ${targetPoint.y}
- `;
- return options.raw ? Path.parse(pathData) : pathData;
- },
- true
- );
- // 括号
- Graph.registerConnector(
- "bracket-branch-connector",
- function (sourcePoint, targetPoint, routerPoints, options) {
- const midX = sourcePoint.x + (sourcePoint.x < targetPoint.x ? 20 : -20);
- const midY = sourcePoint.y;
- const pathData = `
- M ${sourcePoint.x} ${sourcePoint.y}
- Q ${midX} ${midY} ${midX} ${sourcePoint.y + (sourcePoint.y < targetPoint.y ? 20 : -20)}
- L ${midX} ${targetPoint.y + (targetPoint.y < sourcePoint.y ? 20 : targetPoint.y === sourcePoint.y ? 0 : -20)}
- Q ${midX} ${targetPoint.y} ${midX + (targetPoint.x < sourcePoint.x ? -20 : 20)} ${targetPoint.y}
- `;
- return options.raw ? Path.parse(pathData) : pathData;
- },
- true
- );
- Graph.registerConnector(
- "bracket-sub-connector",
- function (sourcePoint, targetPoint, routerPoints, options) {
- const midX = sourcePoint.x + (sourcePoint.x < targetPoint.x ? 10 : -10);
- const midY = sourcePoint.y;
- const pathData = `
- M ${sourcePoint.x} ${sourcePoint.y}
- Q ${midX} ${midY} ${midX} ${sourcePoint.y + (sourcePoint.y < targetPoint.y ? 10 : -10)}
- L ${midX} ${targetPoint.y + (targetPoint.y < sourcePoint.y ? 10 : targetPoint.y === sourcePoint.y ? 0 : -10)}
- Q ${midX} ${targetPoint.y} ${midX + (targetPoint.x < sourcePoint.x ? -10 : 10)} ${targetPoint.y}
- `;
- return options.raw ? Path.parse(pathData) : pathData;
- },
- 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,
- options?: Record<string, any>
- ) => {
- // 树状结构图
- if (structure === StructureType.tree) {
- return `tree-${type}-connector`;
- }
- // 组织结构图
- if (structure === StructureType.organization) {
- return `organization-${type}-connector`;
- }
- // 时间图
- 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`;
- } else {
- return `${themeObj.subConnector}-${type}-connector`;
- }
- };
- const getSourceAnchor = (
- type: TopicType,
- structure: StructureType,
- options?: Record<string, any>
- ) => {
- switch (structure) {
- case StructureType.left: {
- return type === TopicType.branch
- ? {
- name: "center",
- }
- : {
- name: "left",
- };
- }
- case StructureType.right: {
- return type === TopicType.branch
- ? {
- name: "center",
- }
- : {
- name: "right",
- };
- }
- case StructureType.leftRight: {
- return type === TopicType.branch
- ? "center"
- : options?.direction === "left"
- ? "left"
- : "right";
- }
- case StructureType.tree: {
- return type === TopicType.branch
- ? {
- name: "bottom",
- args: {
- dy: -5,
- },
- }
- : {
- name: "bottomLeft",
- args: {
- dx: 10,
- },
- };
- }
- case StructureType.organization: {
- return {
- name: "bottom",
- };
- }
- case StructureType.leftBracket: {
- return {
- name: "left",
- args: {
- dx: -10,
- },
- };
- }
- case StructureType.rightBracket: {
- return {
- name: "right",
- args: {
- dx: 10,
- },
- };
- }
- 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,
- options?: Record<string, any>
- ) => {
- switch (structure) {
- case StructureType.left: {
- return {
- name: "right",
- };
- }
- case StructureType.right: {
- return {
- name: "left",
- };
- }
- case StructureType.leftRight: {
- return options?.direction === "left" ? "right" : "left";
- }
- case StructureType.tree: {
- return type === TopicType.branch
- ? {
- name: "top",
- }
- : {
- name: "left",
- };
- }
- case StructureType.organization: {
- return {
- name: "top",
- };
- }
- case StructureType.leftBracket: {
- return {
- name: "right",
- args: {
- dx: 10,
- },
- };
- }
- case StructureType.rightBracket: {
- return {
- name: "left",
- args: {
- dx: 10,
- },
- };
- }
- 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:
- return {
- name: type === TopicType.branch ? "bottom" : "left",
- };
- case StructureType.leftTreeShape:
- case StructureType.rightTreeShape:
- case StructureType.treeShape: {
- return "left";
- }
- }
- return {
- name: "center",
- args: {
- dx: "25%",
- },
- };
- };
- /**
- * 创建连线
- * @param graph
- * @param sourceId
- * @param item
- * @param structure
- * @param theme
- * @returns
- */
- export const createEdge = (
- graph: Graph,
- sourceId: string,
- item: { id: string; data: TopicItem },
- structure: StructureType,
- theme: string,
- options: Record<string, any> = {}
- ): Edge => {
- return graph.createEdge({
- id: item.id + "-edge",
- inherit: "edge",
- connector: {
- name: getConnector(structure, theme, item.data.type, options),
- },
- zIndex: 0,
- source: {
- cell: sourceId,
- anchor: getSourceAnchor(item.data.type, structure, options),
- },
- target: {
- cell: item.id,
- anchor: getTargetAnchor(item.data.type, structure, options),
- },
- attrs: {
- line: {
- targetMarker: "",
- stroke: item.data.edge?.color || "#A2B1C3",
- strokeWidth: item.data?.edge?.width || 3,
- },
- },
- });
- };
|