antv G6使用之自定义behavior
前言
刚做的一个项目,使用antv g6中的treeGraph画的一棵树,需求需要对节点进行增加、删除、权重设置、指标定义等(总之就是选中节点然后对节点进行一些操作),刚开始使用的是g6 内置的behavior:click-select,后面需求更改,要求能单击依次选中再次单击再取消或者点击画布取消,以我目前的技术以及查阅到的资料来看,内置behavior的选中只能使用trigger属性结合键盘进行多选,纯靠鼠标单击是没办法完成的
内置behavior:click-select
点击节点选中,再次点击节点或者画布取消选中
- 直接在创建画布时的modes中配置默认行为,如:
const graph = new G6.TreeGraph({
modes: {
default: ['drag-node'],
},
});
- 可配置选中的样式,以及选中需要进行的操作。配置样式如:
const graph = new G6.TreeGraph({
modes: {
default: ['drag-node'],
},
nodeStateStyles:{
selected: {
fill: "#EAEAEA",
stroke:
}
});;
选中的操作根据自己项目需求进行设计。
3. 如果需要多选,使用multiple,true为多选,false为不可多选,默认为true,再使用trigger配置用什么键进行多选,默认为shift,可配置shift、ctrl、alt;
const graph = new G6.TreeGraph({
modes: {
default: [
{
type: 'click-select',
multiple:true, //可不配置,默认值为true
trigger: 'ctrl',
},
],
},
});
- 需要对选中节点进行操作的话,可用setState hook设置选中节点,如先前设置
const [selectedItems, setSelectedItems] = ReactuseState<{
nodes: INode[];
edges: IEdge[];}>({
nodes: [],
edges: []
});
就可以对画布添加时机事件,如:
graph.on("nodeselectchange", (e:any) => {
setSelectedItems(e.selectedItems);});
- 还可以通过shouldBegin(e)阻止或允许该行为发生,如,我的项目中只能叶子节点进行选中操作,
const graph = new G6.TreeGraph({
modes: {
default: [
{
type: 'click-select',
multiple:true, //可不配置,默认值为true
trigger: 'ctrl',
shouldBegin:(e) => {
if (e.item.getModel().children !== null) return false; //返回为false即阻止当前行为发生
return true;
}
},
],
},
});;
自定义behavior:clicked-node
- 配置自定义行为,我的项目中配置名称为clicked-node,点击后将节点状态clicked设为true,再次点击或者点击画布后设置clicked状态为false;
- 自定义行为具体可配置哪些方法(如节点点击、边点击、节点拖动等等)可参考antv g6的官网api;
- getEvent 返回该 Behavior 所需监听事件的对象,具体支持也可查看官网事件api
具体代码如下:
/* 使用registerBehavior可以自定义行为,第一个参数为配置的行为名称,
后面使用的时候才可使用,第二个参数为具体方法 */
G6.registerBehavior('activate-node', {
getDefaultCfg() {
return {
multiple: true //设置可多选
};
},
//监听事件的对象,后续就使用onNodeClick和onCanvasClick方法
getEvents() {
return {
'node:click': 'onNodeClick',
'canvas:click': 'onCanvasClick'
};
}
onNodeClick(e) {
const graph = this.graph;
const item = e.item;
//如果当前点击的节点clicked状态已经是true的话,就设置为false,以实现点击选中再次点击取消选中
if (item.hasState('clicked')) {
graph.setItemState(item, 'clicked', false);
return;
}
// 置点击的节点状态 'clicked' 为 true
graph.setItemState(item, 'clicked', true);
},
//点击画布取消所有节点的选中
onCanvasClick(e) {
// shouldUpdate 可以由用户复写,返回 true 时取消所有节点的 'clicked' 状态,即将 'clicked' 状态置为 false
if (this.shouldUpdate(e)) {
removeNodesState();
}
},
//改方法为取消选中方法
removeNodesState() {
//查找所有节点的clicked状态,如果为true就设置为false
graph.findAllByState('node', 'clicked').forEach(node => {
graph.setItemState(node, 'active', false);
});
}
});
- 配置好方法后的使用,我把他配置到了默认行为中,官网解释也可以配置在行为模式中,还没有具体研究
const graph = new G6.TreeGraph({
container: 'mountNode',
width: 1200,
height: 450,
modes: {
default: [
{
type:"clicked-node", //刚刚配置自定义行为的名称
//这里是项目中需要的阻止非叶子节点的选中
shouldBegin:(e) => {
if (e.item.getModel().children !== null) return false
return true
}
],
},
});
- graph监听点击事件(具体逻辑根据项目需求来设置):
graph.on("node:click", (evt:any) => {
//要将点击的添加至所有选中,则找到我们点击事件设置的clicked的状态,即未选中的节点
const nodes = graph.findAllByState('node', 'active')
let selected = {
nodes:[],
edges:[]
}
selected.nodes = nodes
setSelectedTaskItems(selected)
});
- 要对选中的节点进行各种操作,需要在注册自定义行为及配置好行为后,在实例化画布的时候可对画布添加之前注册的时候监听的事件对象进行操作(getEvent方法中的配置),如之前我配置的node:click及canvas:click,不好详细解释,这里以我的项目中删除节点进行代码举例,该删除逻辑是找到所有叶子节点,多选节点,删除时给后端传的参数是所有叶子节点中除去选中的节点。
const onCreateSubTree = (id:string) => {
//selectedTaskItem就是选中的节点,结构为一个数组
if (!selectedTaskItem.nodes.length) return;
const node = selectedTaskItem.nodes[0];
//getTreeLeaf方法没贴出来,该方法的作用是找到整棵树的所有叶子节点的数据,childrenIds是叶子节点的id
const children = getTreeLeaf(data, [])
const childrenIds = children.map((item:any) =>item.id)
//selectedIds,选中的节点的id
const selectedIds = selectedTaskItem.nodes.map((item:any) => item._cfg.id)
//diff,所有节点中除去选中的节点剩余的节点
const diff = childrenIds.filter(function (val) {return selectedIds.indexOf(val) === -1 })
const model = node.getModel();
//接口没有贴真实的
getAjax.xxx({
param:{
indexIds:diff.toString()
},
})
}