123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- import { useState, useRef, useEffect } from 'react'
- import { Cell, Graph, Node } from '@antv/x6'
- import { Dnd } from '@antv/x6-plugin-dnd'
- import { Transform } from '@antv/x6-plugin-transform'
- import { Snapline } from '@antv/x6-plugin-snapline'
- import { Clipboard } from '@antv/x6-plugin-clipboard'
- import { Selection } from '@repo/x6-plugin-selection/src/index'
- import { History } from '@antv/x6-plugin-history'
- import { Keyboard } from '@antv/x6-plugin-keyboard'
- import { Export } from '@antv/x6-plugin-export'
- import { useModel } from 'umi'
- import '@/components/PageContainer'
- import { handleGraphEvent } from '@/events/flowEvent'
- import { pageMenu, nodeMenu} from '@/utils/contentMenu';
- import { bindKeys } from '@/utils/fastKey'
- export default function GraphModel() {
- const [graph, setGraph] = useState<Graph>();
- const [dnd, setDnd] = useState<Dnd>();
- const pageNodeRef = useRef<Node>();
- const dndRef = useRef(dnd);
- // 画布
- const graphRef = useRef<Graph>();
- const { pageState } = useModel('appModel');
- // 当前选中的节点
- const [selectedCell, setSelectedCell] = useState<Cell[]>([]);
- const [canRedo, setCanRedo] = useState(false);
- const [canUndo, setCanUndo] = useState(false);
- /**初始化页面节点 */
- useEffect(() => {
- if(pageState.width && graphRef.current && !pageNodeRef.current) {
- const graph = graphRef.current;
- pageNodeRef.current = graph?.addNode({
- shape: 'page-container-node',
- width: pageState.width,
- height: pageState.height,
- zIndex: -1,
- data: {
- isPage: true,
- ignoreDrag: true,
- ...pageState
- },
- tools: [
- {
- name: 'contextmenu',
- args: {
- menu: pageMenu,
- },
- },
- ]
- });
- };
- }, [pageState.width, graphRef.current])
- useEffect(() => {
- pageNodeRef.current?.setData({
- background: pageState.backgroundColor,
- ...pageState
- });
- pageNodeRef.current?.setSize({
- width: pageState.width,
- height: pageState.height
- })
- }, [pageState]);
- const enabledTransform = (node: Node) => {
- const data = node.getData<{ isPage: boolean, lock: boolean }>();
- return !data?.isPage && !data?.lock;
- }
- /**初始化画布 */
- const initGraph = (instance: Graph) => {
- // 添加插件
- instance
- .use(
- new Transform({
- resizing: {
- enabled: enabledTransform,
- minWidth: 20,
- minHeight: 20
- },
- rotating: {
- enabled: enabledTransform,
- grid: 1
- },
- }),
- )
- .use(
- new Selection({
- enabled: true,
- multiple: true,
- rubberband: true,
- movable: true,
- showNodeSelectionBox: true,
- // showEdgeSelectionBox: true,
- pointerEvents: 'none',
- strict: true,
- filter: (cell: Cell) => {
- const data = cell.getData<{ isPage: boolean, lock: boolean }>();
- return !data?.isPage && !data?.lock;
- },
- }),
- )
- .use(new Snapline({
- sharp: true,
- resizing: true
- }))
- .use(new Keyboard({
- enabled: true,
- global: true,
- }))
- .use(new Clipboard())
- .use(new History({
- enabled: true,
- beforeAddCommand: (event, args) => {
- // @ts-ignore 排除不用创建的节点
- if(args?.cell?.data?.noCreate) return false;
- // @ts-ignore 排除页面节点
- return !(event === 'cell:added' && args?.cell?.getData()?.isPage);
- },
- }))
- .use(new Export());
- setGraph(instance);
- graphRef.current = instance;
- // 选中的节点/边发生改变(增删)时触发
- instance.on('selection:changed', ({selected}: {added: Cell[]; removed: Cell[]; selected: Cell[];}) => {
- setSelectedCell(selected);
- })
- instance.on('history:change', () => {
- setCanRedo(instance.canRedo());
- setCanUndo(instance.canUndo());
- })
- // 通用事件处理
- handleGraphEvent(instance);
- // 绑定快捷键
- bindKeys(instance);
- }
- /**初始化拖拽 */
- const initDnd = (instance: Dnd) => {
- setDnd(instance);
- dndRef.current = instance;
- }
- /**组件库拖拽生成 */
- const startDrag = (e: React.MouseEvent<HTMLDivElement, MouseEvent>, node: Node.Metadata) => {
- if(!dndRef.current || !graphRef.current) return;
- // 往画布添加节点
- const n = graphRef.current.createNode(node);
- // 右键菜单
- n.addTools({
- name: 'contextmenu',
- args: {
- menu: nodeMenu,
- },
- });
- dndRef.current.start(n, e.nativeEvent as any)
- };
- // 撤销
- const onUndo = () => {
- graphRef.current?.undo();
- }
- // 重做
- const onRedo = () => {
- graphRef.current?.redo();
- }
- return {
- graph,
- dnd,
- initGraph,
- initDnd,
- startDrag,
- selectedCell,
- canRedo,
- canUndo,
- onUndo,
- onRedo
- };
- };
|