xflow流程可视化-自定义节点
时间:2023-03-28 18:54:45
HTML
上一篇文章主要展示和修改可视化页面。本文主要讲解自定义节点。流程图节点组件上一页左侧的流程节点组件为FlowchartNodePanel。该组件基于NodeCollapsePanel进行封装。它提供了一些内置的公共节点,你也可以添加一些自定义节点,但缺点是内置节点我们无法添加。自定义属性,因此只能用于绘图显示,对工艺节点没有实际意义。所以在这里我们删除了FlowchartNodePanel并将其替换为更具扩展性(原始)的NodeCollapsePanel。但是NodeCollapsePanel的很多方法需要我们自己添加。本文将一步步讲解。流程节点有两点需要注意,一是左边的节点列表,这个列表提供了在主视图中添加的可拖动节点,二是在主视图中显示的节点(反向显示和拖动显示),这两个节点实际上都是使用流程节点组件提供的。自定义节点首先,我们删除上一章的组件FlowchartNodePanel,新建文件夹CustomNodeCollapsePanel,新建index.tsx和config-dnd-panel.tsx,前者是我们自定义的左组件,后者是自定义节点每个方法//index.tsximport{NodeCollapsePanel}from'@antv/xflow';import{FC}from'react';import*aspanelConfigfrom'./config-dnd-panel';constCustomNodeCollapsePanel:FC=()=>{return(Footer
}onNodeDrop={panelConfig.onNodeDrop}searchService={panelConfig.searchService}nodeDataService={panelConfig.nodeDataService}position={{top:40,bottom:0,left:0,width:290}}/>);};exportdefaultCustomNodeCollapsePanel;searchService是搜索节点,onNodeDrop是主视图左侧节点列表拖动的回调。我们使用它在主视图上创建节点。nodeDataService返回我们的节点列表的数组。接下来,我们将对几个方法一一添加说明:渲染节点列表从'导入节点。/节点';constrenderNode=(props:{data:NsNodeCollapsePanel.IPanelNode;isNodePanel:boolean;},style:{width:number;height:number},)=>{constNode=Nodes[props.data.renderKey!];返回节点?
:null;};constnodeList=(arr:any[])=>{constnewArr=arr.map((s)=>{constattrs=s.attrs;return{popoverContent:()=>
{s.label}/div>,renderKey:s.renderKey||'CustomNode',renderComponent:(props:any)=>renderNode(props,attrs.style),label:s.label,id:s.id,attrs:attrs,...attrs.canvansStyle,};});返回newArr;};exportconstnodeDataService:NsNodeCollapsePanel.INodeDataService=async()=>{//这里可以通过接口获取节点列表constresData=[{id:1,renderKey:'CustomNode',label:'start',attrs:{style:{width:280,height:40,},canvasStyle:{width:120,height:40,},},},{id:2,renderKey:'CustomConnecto',label:'AuditNode',attrs:{style:{width:80,height:80,},canvasStyle:{width:80,height:80,},},},];返回[{id:'NODE',header:'node',children:nodeList(resData),},];};我们将接口返回的节点属性转换成面板Dnd节点所需的属性结构,我这里声明了两种宽高,主要是一种用于画布主视图中显示的节点的宽高,一种用于节点列表中组件的宽度和高度。我们的节点渲染其实是通过renderComponent返回的组件来进行渲染的,renderKey的作用就是在我们view上已经存在的节点反转的时候,根据renderKey渲染节点列表中对应的节点。自定义节点新建一个CustomNodeCollapsePanel/Nodes/index.ts,这里我们使用批量导出,在Nodes中为每个节点创建一个文件夹,使用index.ts进行批量导出,首先安装解析require.context的包yarnadd@types/webpack-env-D//index.tsconstfiles=require.context('.',true,/index\.tsx$/);const模块:{[key:string]:any}={};functionisPromise(obj:Promise
|null|undefined){return(obj!==null&&obj!==undefined&&typeofobj.then==='function'&&typeofobj.catch==='function');}files.keys().forEach(async(key)=>{constpathArr=key.replace(/(\.\/|\.tsx)/g,'').split('/');pathArr.pop();constmoduleName=pathArr.join('/').replace(/\/\w{1}/g,function(val){returnval.substring(1,2).toUpperCase();}});constmodule=isPromise(files(key))?awaitfiles(key):files(key);modules[moduleName]=module.default;});exportdefaultmodules;require.context是提供的检索apiwebpack,这里多了一个Promise的判断,如果umi开启了mfsu,得到的模块会是按需异步导出,所以判断过程,这个index.ts的作用是遍历Nodesindex.tsx中的所有目录,然后组装成一个对象返回,如:aaa/bbb/index.tsxccc/index.tsx{aaaBbb:moduleccc:module}接下来,我们创建我们的自定义节点CustomNode和CustomConnecto同样跳过,新建一个Nodes/CustomNode/index.tsx:importtype{FC}from'react';从'@antv/xflow'导入类型{NsNodeCollapsePanel};从'./index.less'导入样式;interfaceCustomNodeProps{data:NsNodeCollapsePanel.IPanelNode;isNodePanel:布尔值;style:React.CSSProperties;}constCustomNode:FC=({data,style,isNodePanel})=>{return({data.label});};exportdefaultCustomNode;index.less:.customNode{width:100%;高度:100%;border:1pxsolidrgb(162,177,195);显示:弹性;证明内容:居中;对齐项目:居中;边界半径:4px;&:global(.isNodePanel){边框颜色:红色;}}这里我们创建一个简单的节点,接受传入的节点属性和样式,可以使用isNodePanel的值用来区分节点列表渲染和主视图逆向渲染。当为真时为前者,否则为后者,所以这个值可以用于不同的回报。比如组件列表是一个圆形,拖到主视图上就可以变成一个正方形。当然,我们这里只是简单的修改一下边框的颜色。您可以自行修改样式。需要注意的是节点样式的宽高是不能写死的,因为我们主画布上的图形是可以拖动改变宽高的,所以我们接受传入样式的宽高作为初始宽度和高度。在画布视图中渲染节点时,我们使用setNodeRender将renderKey设置为CustomNode,并使用我们的CustomNode组件进行渲染。//config-dnd-panel.tsxexportconstuseGraphConfig:IFlowchartGraphProps['useConfig']=(config)=>{Object.keys(Nodes).map((key)=>{config.setNodeRender(key,(props)=>{returnrenderNode({data:props.data,isNodePanel:false},props.size);});});};//Xflow/index.tsximport{useGraphConfig}from'./CustomNodeCollapsePanel/config-dnd-panel';
...拖拽生成节点我们来拖拽左边的组件list拖动到主视图时会触发OnNodeDrop。我们在这个事件中添加节点://CustomNodeCollapsePanel/index.tsximport{NsNodeCollapsePanel,NsNodeCmd,uuidv4,XFlowNodeCommands,IFlowchartGraphProps,}from'@antv/xflow';importgetPortsfrom'./ports';exportconstonNodeDrop:NsNodeCollapsePanel.IOnNodeDrop=async(nodeConfig,commandService,)=>{constargs:NsNodeCmd.AddNode.IArgs={nodeConfig:{...nodeConfig,id:uuidv4(),ports:getPorts()},};ommandService.executeCommand(XFlowNodeCommands.ADD_NODE.id,args,);};当然,添加节点还不够,节点还需要连接,所以我们新建一个ports.ts来生成连接Requiredconnectionstub://CustomNodeCollapsePanel/ports.tsimport{uuidv4}from'@antv/xflow';constgetAnchorStyle=(position:string)=>{return{position:{name:position},attrs:{circle:{r:4,magnet:true,stroke:'#31d0c6',strokeWidth:2,fill:'#}fff',样式:{可见性:'隐藏',},},},zIndex:10,};};constgetPorts=(position=['top','right','bottom','left'])=>{return{items:position.map((name)=>{return{group:name,id:uuidv4()};}),groups:{top:getAnchorStyle('top'),right:getAnchorStyle('right'),bottom:getAnchorStyle('底部'),左:getAnchorStyle('左'),},};};导出默认的getPorts;搜索节点最后我们添加搜索节点的功能://CustomNodeCollapsePanel/index...关键词));返回列表;};自定义节点反显测试我们添加几个自定义节点,将它们连接起来,点击save时将数据存入localStorage,然后在onLoad时赋值看看我们的自定义节点反显是否正常://Xflow/config-toolbar.ts找到saveGraphDataService:saveGraphDataService:(meta,graphData)=>{console.log(graphData);localStorage.setItem('graphData',JSON.stringify(graphData));returnnull;},//Xflow/index.tsxconstonLoad:IAppLoad=async(app)=>{graphRef.current=awaitapp.getGraphInstance();}constgraphData:NsGraph.IGraphData=JSON.parse(localStorage.getItem('graphData')!,)||{节点:[],边缘:[]};等待app.executeCommand(XFlowGraphCommands.GRAPH_RENDER.id,{graphData:graphData,},);//中心等待app.executeCommand(XFlowGraphCommands.GRAPH_ZOOM.id,{factor:'real',},);图绑定();};好了,我们的自定义节点就基本完成了,实现了左列表节点和样式,主视图节点和样式,添加连接桩,连接线,主视图反向显示等功能,不过这时候原来的节点编辑功能就权限有些失效,目前的编辑功能不能满足我们的需求。Next下一篇文章将介绍自定义节点的编辑功能,在自定义节点上编辑各种属性,期待本文地址:链接本文github地址:链接github演示地址:链接