问题1. 部分分组中节点拖拽添加或操作后撤销重做操作不生效。
前提:使用Stencil插件,创建画布侧边栏的 UI 组件,同时使用其分组、折叠能力。分组包含固定分组、后台接口获取的动态分组和组件。
//固定分组初始化
initStencil (graph, stencil) {
//defaultGroup是固定分组和其节点信息,自行添加defaultGroup.forEach((gp, index) => {const groupName = 'common-group' + indexconst group = { name: groupName, title: gp.name || '未命名', collapsable: true }stencil.addGroup(group)const nodes = gp.children.map(item => {let nodeif (item.data.nodeType !== specilNodeType.GroupNodeType) {node = graph.createNode({shape: 'custom-vue-node',width: 166,height: 32,data: { nodeGroup: gp.key, ...item, ...(item.data || {}), isStencil: true, data: null }})} else {node = graph.createNode({shape: 'group-vue-node',width: 166,height: 32,data: { nodeGroup: gp.key, ...item, ...(item.data || {}), isStencil: true, data: null }})}return node})stencil.load(nodes, groupName)})// 重要,动态添加分组后手动调用一下startListening,否则新增的分组无法监听鼠标按下事件stencil.startListening()},//动态分组创建createStencilNode (graph, stencil, componentList) {Object.keys(componentList).forEach((key, index) => {const groupName = 'group' + indexconst group = { name: groupName, title: key || '未命名', collapsable: true }stencil.addGroup(group)const nodes = componentList[key].map(item => {const {abilityParamList = [],serviceName = '未知',productType,resType,serviceId,serviceType,serviceDescription,tags,icon, priority} = itemconst node = graph.createNode({shape: 'custom-vue-node',width: 166,height: 32,data: {name: serviceName,icon,nodeGroup: key, // 分组productType,resType,serviceId,serviceType,serviceDescription,tags,priority,strategyConfig: [],isStencil: true}})return node})stencil.load(nodes, groupName)})// 重要,动态添加分组后手动调用一下startListening,否则新增的分组无法监听鼠标按下事件stencil.startListening()},
**问题:**固定分组中的节点拖拽入画布后画布的撤销重做操作无法使用,如果不拖拽加入固定分组中的节点,撤销重做操作正常。
解决:
由于固定分组是画图初始化完就添加的,而动态分组时后面通过接口返回添加的,为了避免新增的分组无法监听鼠标按下事件,固分别执行了stencil.startListening()方法。导致固定分组中执行了两个监听。固在第二次执行该方法前,调用stencil.stopListening()
取消之前的监听事件,这里添加在动态创建分组方法中
//动态分组创建createStencilNode (graph, stencil, componentList) {// 避免之前初始化的侧边节点拖拽后无法使用撤销重做操作问题stencil.stopListening()Object.keys(componentList).forEach((key, index) => {const groupName = 'group' + indexconst group = { name: groupName, title: key || '未命名', collapsable: true }stencil.addGroup(group)const nodes = componentList[key].map(item => {const {abilityParamList = [],serviceName = '未知',productType,resType,serviceId,serviceType,serviceDescription,tags,icon, priority} = itemconst node = graph.createNode({shape: 'custom-vue-node',width: 166,height: 32,data: {name: serviceName,icon,nodeGroup: key, // 分组productType,resType,serviceId,serviceType,serviceDescription,tags,priority,strategyConfig: [],isStencil: true}})return node})stencil.load(nodes, groupName)})// 重要,动态添加分组后手动调用一下startListening,否则新增的分组无法监听鼠标按下事件stencil.startListening()},
问题2、使用Stencil的过滤能力时,过滤后分组高度无法根据过滤后的组件自适应。仍然保持过滤前的高度
前提: 使用Stencil插件的过滤功能
问题: Stencil中分组容器的高度在加载分组时就确定了。后面不会根据里面的节点个数改变,且里面的节点是通过svg标签包裹的,没办法动态设置其高度。
过滤前:
过滤后:
解决: 在过滤方法中为满足过滤条件的节点添加一个属性设置其为true,最后获取分组中包含该属性的节点,即过滤展示的节点,根据节点个数动态设置分组的高度。
import { Stencil } from '@antv/x6-plugin-stencil'
export default class GraphFlow {
//其他方法自行定义graph;stencil;timer;
refreshStencilHeight (model, stencil) {if (this.timer) {clearTimeout(this.timer)}this.timer = setTimeout(() => {Object.keys(model.groups).forEach(name => {const nodes = model.graphs?.[name]?.model?.getNodes() || []const index = nodes.filter(it => {return it.getData()?.isMatched})const height = index.length * 36 + 18stencil.resizeGroup(name, { height })})}, 500)
}initStencil (stencilContainer) {const that = thisconst stencil = new Stencil({title: '',target: this.graph,search (cell, keyword) {const { name } = cell.getData() || {}that.refreshStencilHeight(this, stencil)if (name && name.indexOf(keyword) !== -1) {// 标识过滤匹配成功,解决过滤后分组高度显示无法自适应问题cell.setData({ isMatched: true })}return name && name.indexOf(keyword) !== -1},placeholder: '请输入',notFoundText: '暂无数据',stencilGraphWidth: 200, // 组宽度stencilGraphHeight: 0, // 模板画布高度。设置为 0 时高度会自适应// collapsable: true, // 如果不设置则第一个group的title显示不出来groups: [],layoutOptions: {columns: 1,columnWidth: 180, // 这个值要和group的值对应要不然可能会定位不准确rowHeight: 36, // 行高,会影响节点之间的高度间隔resizeToFit: true}})stencilContainer.appendChild(stencil.container)this.stencil = stencil
}
}