import React, { useEffect, useRef, useCallback } from 'react' import G6, { Graph } from '@antv/g6/dist/g6.min.js' import { withoutUndo } from 'mobx-keystone' import { useSize } from 'ahooks' import { useMst } from '../context' import register from './item' import { observer } from 'mobx-react-lite' import ToolBar from '../components/model-toolbar' import './model.scss' import GraphEvent from './event' import { initStyle } from './item/style' import { useUpdateItem } from './hooks' import { RootInstance } from '../type' // import { debounce } from 'lodash' // import mst from 'test/mst' export default observer(() => { // const mst = useMst() const { setRef, erdGraph, containerRef } = useLocal() // const size = useSize(containerRef); return ( <> {/* <div>{mst.sys.checkedKeys.length}</div> */} {/* {JSON.stringify(size)} */} <ToolBar graph={erdGraph} /> <div ref={setRef} className='graph' /> </> ) }) const useLocal = () => { const mst = useMst() // window.kkk = mst const containerRef = useRef(null) const erdGraphRef = useRef<Graph>(null) const miniMapRef = useRef<any>(null) useEffect(() => { register(mst) }, []) const checkRef = useRef(+new Date()) const size = useSize(containerRef); useEffect(() => { // alert() // const { Nodes , edges } = mst if (!erdGraphRef.current) { // alert(mst.Nodes.length) // alert(mst === window.kkk) //alert('erdGraphRef.current = render') const Obj = render(containerRef.current, mst.Nodes, mst.edges, mst) erdGraphRef.current = Obj.graph miniMapRef.current = Obj.miniMap //alert('erdGraphRef.current') // alert(mst.graph.$modelId) async(() => { mst.graph.setG6Graph(erdGraphRef.current) // layout(erdGraphRef.current, Nodes , edges, mst) }) // window.kkk1 = mst } else { //alert(' layout(erdGraphRef.current, mst.Nodes ' + mst.Nodes.length) layout(erdGraphRef.current, mst.Nodes, mst.edges, mst) // erdGraphRef.current.fitView(0) } }, [JSON.stringify(mst.sys.checkedKeys), mst]) useEffect(() => { if (erdGraphRef.current && size.width && size.height) { // alert(erdGraphRef.current['isLayouting']) if (!erdGraphRef.current['isLayouting']) { const documentHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight const height = mst.sys.height === '100%' ? documentHeight - 45 : (mst.sys.height as number) - 45 erdGraphRef.current.changeSize(size.width, height) erdGraphRef.current.fitView(0) } } }, [size.height, size.width]) const setRef = useCallback( ref => { containerRef.current = ref }, [containerRef] ) useEffect(() => { // debounce(()=> { const graph = erdGraphRef.current if (graph) { const gwidth = graph.get('width') const gheight = graph.get('height') const point = graph.getCanvasByPoint(gwidth / 2, gheight / 2) graph.zoomTo(mst.graph.zoom, point) } // } // }, 100)() }, [mst.graph.zoom]) const reloadRef = useRef(false) useEffect(() => { // debounce(()=> { const graph = erdGraphRef.current if (graph) { if (!reloadRef.current) { reloadRef.current = true return } // alert() // graph.clear() // graph.data({ nodes: mst.Nodes, edges: mst.edges }) // graph.render() const isLargar = graph.getNodes().length > 50 graph.updateLayout({ type: mst.sys.dagreLayout ? 'dagre' : 'fruchterman', // condense: true, // cols: 3, workerEnabled: true, linkDistance: 0, pixelRatio: 2, // alphaDecay: isLargar ? 0.3 : 0.15, // preventOverlap: true, // clustering: true, clusterGravity: 100, speed: 2, gravity: 100, gpuEnabled: true, // collideStrength: 0.5, // type: 'dagre', // // controlPoints: true, // // nodeSize: [40, 20], // nodesep: 1, // ranksep: 1, // align: 'DL', // nodesep: 100, // 节点水平间距(px) // ranksep: 200, // 每一层节点之间间距 // nodeSpacing: isLargar ? -100 : -180, onLayoutEnd: () => { async(() => { // alert() graph['isLayouting'] = false // graph['isLayouting'] = false // alert('endlayout') graph.fitView(0) withoutUndo(() => { mst.graph.setZoom(graph.getZoom()) }) // alert('onLayoutEnd') }, 1000) } }) if (mst.sys.dagreLayout) { async(() => { // alert() graph.fitView(0) }, 1000) } } }, [mst.sys.dagreLayout]) // alert('useUpdateItem' + mst.graph.zoom) useUpdateItem({ currentModel: mst.sys.currentModel, graph: erdGraphRef.current as any, showNameOrLabel: mst.sys.showNameOrLabel, zoom: mst.graph.zoom, checkNum: checkRef.current, themeColor: mst.Ui.themeColor, darkness: mst.Ui.darkness }) useEffect(() => { if (erdGraphRef.current && miniMapRef.current) { // alert() if (!mst.sys.disableMiniMap) { erdGraphRef.current?.removePlugin(miniMapRef.current) } else { const miniMap = new G6.Minimap({ type: 'delegate', viewportClassName: 'g6-minimap-viewport-erd', delegateStyle: { fill: 'rgba(0,0,0,0.10)' } }) miniMapRef.current = miniMap erdGraphRef.current?.addPlugin(miniMap) } } }, [mst.sys.disableMiniMap]) return { containerRef, setRef, erdGraph: erdGraphRef.current } } // const MINZOOM = 0.01 // const toolbar = new G6.ToolBar(); // const edgeBundling = new G6.Bundling({ // bundleThreshold: 0.6, // K: 100, // }); const render = (container: any, nodes: any, edges: any, mst: RootInstance) => { const documentHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight const height = mst.sys.height === '100%' ? documentHeight - 45 : (mst.sys.height as number) - 45 // const height = mst.sys.height // alert(height) // alert(height) const styleConfig = initStyle({ primaryColor: mst.Ui.themeColor }).style const isLargar = nodes.length > 50 // alert(isLargar) const miniMap = new G6.Minimap({ type: 'delegate', viewportClassName: 'g6-minimap-viewport-erd', delegateStyle: { fill: 'rgba(0,0,0,0.10)' } }) const graph = new G6.Graph({ height, width: container.offsetWidth - 20, container, fitView: true, // workerEnabled: true, fitCenter: true, enabledStack: true, animate: true, gpuEnabled: true, pixelRatio: 2, // pixelRatio: 1, // animate: true, defaultEdge: styleConfig.default.edge, edgeStateStyles: { default: styleConfig.default.edge, active: { opacity: 1, size: 3 } }, minZoom: 0.01, maxZoom: 1.1, layout: { type: mst.sys.dagreLayout ? 'dagre' : 'force', condense: true, cols: 3, // gpuEnabled: true, workerEnabled: true, // workerScriptURL:'', linkDistance: 0, alphaDecay: isLargar ? 0.3 : undefined, preventOverlap: true, // collideStrength: 0.5, nodeSpacing: isLargar ? -100 : -180, onLayoutEnd: () => { graph['isLayouting'] = false graph['endLayout'] = true graph.fitView(0) graph['endLayout'] = false withoutUndo(() => { mst.graph.setZoom(graph.getZoom()) }) } }, modes: { default: [ 'drag-canvas', { type: 'zoom-canvas', minZoom: 0.0001, // enableOptimize: true, // optimizeZoom: true, maxZoom: 2.1 // enableOptimize: true, }, { type: 'drag-node' // enableDelegate: true, }, { type: 'edge-tooltip', formatText: model => { return model.tooltip as string }, offset: 10 } // { // type: 'activate-relations', // resetSelected: true, // trigger: 'click' // }, ] }, plugins: [ // toolbar, // ...[mst.sys.disableMiniMap ? [] : [miniMap]] ] }) // alert(mst === window.kkk) GraphEvent(graph, mst) // miniMap.init // const x = nodes[0].x // edgeBundling.bundling({ nodes, edges }); graph.data({ nodes, edges }) graph['isLayouting'] = true graph.render() graph.fitView(0) if (mst.sys.dagreLayout) { async(() => { // alert() graph.fitView(0) withoutUndo(() => { mst.graph.setZoom(graph.getZoom()) }) }) } // layout(graph, nodes) return { graph, miniMap } } const layout = (graph: Graph, nodes: any, edges, mst: RootInstance) => { // graph.clear() graph.changeData({ nodes, edges }) // graph.getNodes().filter((a) => !a.isSys).forEach((node: any) => { // // node.x = undefined // // node.y = undefined // const model = node.getModel() // if (!model.visible) { // // node.getContainer().hide() // graph.hideItem(node) // // return // } // }) // const _edges = graph.getEdges() // _edges.forEach((edge: any) => { // let sourceNode = edge.get('sourceNode') // let targetNode = edge.get('targetNode') // const targetModel = targetNode.getModel() // if (!targetModel.visible || !sourceNode.getModel().visible) { // edge.hide() // // return // } // }) // alert(graph.getNodes().length) // const isLargar = graph.getNodes().length > 50 // // alert(isLargar) // graph.isLayouting = true // async(() => graph.updateLayout({ // type: 'force', // condense: true, // // cols: 3, // workerEnabled: true, // linkDistance: 0, // alphaDecay: isLargar ? 0.1 : 0.3, // // preventOverlap: false, // // collideStrength: 0.5, // // nodeSpacing: -1000, // onLayoutEnd: () => { // graph.isLayouting = false // // graph.fitView(0) // alert() // // mst.graph.setZoom(graph.getZoom()) // } // })) // graph.fitView(0) return graph } const async = (fun, time = 500) => { setTimeout(fun, time) }