You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
5.6 KiB
203 lines
5.6 KiB
import shortcuts from '../../common/shortcuts';
|
|
import { Cell, Edge, Graph, Node } from '@antv/x6';
|
|
import { MIN_ZOOM, MAX_ZOOM } from '../../common/const';
|
|
import baseCellSchemaMap from '../../common/baseCell';
|
|
import { getSelectedEdges } from '../../utils/flowChartUtils';
|
|
import { registerServerStorage } from './registerServerStorage';
|
|
import MiniMapSimpleNode from '../../components/miniMapSimpleNode';
|
|
|
|
// X6 register base cell shape
|
|
Object.values(baseCellSchemaMap).forEach((schema) => {
|
|
const { base, ...rest } = schema;
|
|
base.define(rest);
|
|
});
|
|
|
|
const registerEvents = (flowChart: Graph): void => {
|
|
flowChart.on('node:added', (args) => {
|
|
flowChart.cleanSelection();
|
|
flowChart.select(args.cell);
|
|
});
|
|
flowChart.on('selection:changed', () => {
|
|
flowChart.trigger('toolBar:forceUpdate');
|
|
flowChart.trigger('settingBar:forceUpdate');
|
|
});
|
|
flowChart.on('edge:connected', (args) => {
|
|
const edge = args.edge as Edge;
|
|
const sourceNode = edge.getSourceNode() as Node;
|
|
if (sourceNode && sourceNode.shape === 'imove-branch') {
|
|
const portId = edge.getSourcePortId();
|
|
if (portId === 'right' || portId === 'bottom') {
|
|
edge.setLabelAt(0, sourceNode.getPortProp(portId, 'attrs/text/text'));
|
|
sourceNode.setPortProp(portId, 'attrs/text/text', '');
|
|
}
|
|
}
|
|
});
|
|
flowChart.on('edge:selected', (args) => {
|
|
args.edge.attr('line/stroke', '#feb663');
|
|
args.edge.attr('line/strokeWidth', '3px');
|
|
});
|
|
flowChart.on('edge:unselected', (args) => {
|
|
args.edge.attr('line/stroke', '#333');
|
|
args.edge.attr('line/strokeWidth', '2px');
|
|
});
|
|
flowChart.on('edge:mouseover', (args) => {
|
|
args.edge.attr('line/stroke', '#feb663');
|
|
args.edge.attr('line/strokeWidth', '3px');
|
|
});
|
|
flowChart.on('edge:mouseleave', (args) => {
|
|
const { edge } = args;
|
|
const selectedEdges = getSelectedEdges(flowChart);
|
|
if (selectedEdges[0] !== edge) {
|
|
args.edge.attr('line/stroke', '#333');
|
|
args.edge.attr('line/strokeWidth', '2px');
|
|
}
|
|
});
|
|
flowChart.on('node:dblclick', () => {
|
|
flowChart.trigger('graph:editCode');
|
|
});
|
|
flowChart.on('blank:contextmenu', (args) => {
|
|
const {
|
|
e: { clientX, clientY },
|
|
} = args;
|
|
flowChart.cleanSelection();
|
|
flowChart.trigger('graph:showContextMenu', {
|
|
x: clientX,
|
|
y: clientY,
|
|
scene: 'blank',
|
|
});
|
|
});
|
|
flowChart.on('node:contextmenu', (args) => {
|
|
const {
|
|
e: { clientX, clientY },
|
|
node,
|
|
} = args;
|
|
// NOTE: if the clicked node is not in the selected nodes, then clear selection
|
|
if (!flowChart.getSelectedCells().includes(node)) {
|
|
flowChart.cleanSelection();
|
|
flowChart.select(node);
|
|
}
|
|
flowChart.trigger('graph:showContextMenu', {
|
|
x: clientX,
|
|
y: clientY,
|
|
scene: 'node',
|
|
});
|
|
});
|
|
};
|
|
|
|
const registerShortcuts = (flowChart: Graph): void => {
|
|
Object.values(shortcuts).forEach((shortcut) => {
|
|
const { keys, handler } = shortcut;
|
|
flowChart.bindKey(keys, () => handler(flowChart));
|
|
});
|
|
};
|
|
|
|
const createFlowChart = (
|
|
container: HTMLDivElement,
|
|
miniMapContainer: HTMLDivElement,
|
|
): Graph => {
|
|
const flowChart = new Graph({
|
|
container,
|
|
rotating: false,
|
|
resizing: true,
|
|
// https://x6.antv.vision/zh/docs/tutorial/basic/clipboard
|
|
clipboard: {
|
|
enabled: true,
|
|
useLocalStorage: true,
|
|
},
|
|
// https://x6.antv.vision/zh/docs/tutorial/intermediate/connector
|
|
connecting: {
|
|
snap: true,
|
|
dangling: true,
|
|
highlight: true,
|
|
anchor: 'center',
|
|
connectionPoint: 'anchor',
|
|
router: {
|
|
name: 'manhattan',
|
|
},
|
|
validateConnection({
|
|
sourceView,
|
|
targetView,
|
|
sourceMagnet,
|
|
targetMagnet,
|
|
}) {
|
|
if (!sourceMagnet) {
|
|
return false;
|
|
} else if (!targetMagnet) {
|
|
return false;
|
|
} else {
|
|
return sourceView !== targetView;
|
|
}
|
|
},
|
|
},
|
|
// https://x6.antv.vision/zh/docs/tutorial/basic/background
|
|
background: {
|
|
color: '#f8f9fa',
|
|
},
|
|
// https://x6.antv.vision/zh/docs/tutorial/basic/grid
|
|
grid: {
|
|
visible: true,
|
|
},
|
|
// https://x6.antv.vision/zh/docs/tutorial/basic/selection
|
|
selecting: {
|
|
enabled: true,
|
|
multiple: true,
|
|
rubberband: true,
|
|
movable: true,
|
|
strict: true,
|
|
showNodeSelectionBox: false,
|
|
},
|
|
// https://x6.antv.vision/zh/docs/tutorial/basic/snapline
|
|
snapline: {
|
|
enabled: true,
|
|
clean: 100,
|
|
},
|
|
// https://x6.antv.vision/zh/docs/tutorial/basic/keyboard
|
|
keyboard: {
|
|
enabled: true,
|
|
global: false,
|
|
},
|
|
// https://x6.antv.vision/zh/docs/tutorial/basic/history
|
|
history: {
|
|
enabled: true,
|
|
},
|
|
// https://x6.antv.vision/zh/docs/tutorial/basic/minimap
|
|
minimap: {
|
|
width: (150 * container.offsetWidth) / container.offsetHeight,
|
|
height: 150,
|
|
minScale: MIN_ZOOM,
|
|
maxScale: MAX_ZOOM,
|
|
enabled: true,
|
|
scalable: false,
|
|
container: miniMapContainer,
|
|
graphOptions: {
|
|
async: true,
|
|
getCellView(cell: Cell) {
|
|
if (cell.isNode()) {
|
|
return MiniMapSimpleNode;
|
|
}
|
|
},
|
|
createCellView(cell: Cell) {
|
|
if (cell.isEdge()) {
|
|
return null;
|
|
}
|
|
},
|
|
},
|
|
},
|
|
// https://x6.antv.vision/zh/docs/tutorial/basic/scroller
|
|
scroller: {
|
|
enabled: true,
|
|
},
|
|
mousewheel: {
|
|
enabled: true,
|
|
minScale: MIN_ZOOM,
|
|
maxScale: MAX_ZOOM,
|
|
modifiers: ['ctrl', 'meta'],
|
|
},
|
|
});
|
|
registerEvents(flowChart);
|
|
registerShortcuts(flowChart);
|
|
registerServerStorage(flowChart);
|
|
return flowChart;
|
|
};
|
|
|
|
export default createFlowChart;
|
|
|