fix: update edge state with updateItem

This commit is contained in:
baizn 2020-10-10 14:54:18 +08:00 committed by Moyee
parent 518021657b
commit 3a7dd04ed1
4 changed files with 337 additions and 1 deletions

View File

@ -1,4 +1,4 @@
import { isString, isPlainObject, isNil } from '@antv/util';
import { isString, isPlainObject, isNil, mix } from '@antv/util';
import { IEdge, INode, ICombo } from '../interface/item';
import { EdgeConfig, IPoint, NodeConfig, SourceTarget, Indexable } from '../types';
import Item from './item';
@ -212,6 +212,15 @@ export default class Edge extends Item implements IEdge {
const oriVisible = model.visible;
const cfgVisible = cfg.visible;
if (oriVisible !== cfgVisible && cfgVisible !== undefined) this.changeVisibility(cfgVisible);
const styles = this.get('styles');
if (cfg.stateStyles) {
// 更新 item 时更新 this.get('styles') 中的值
const { stateStyles } = cfg;
mix(styles, stateStyles);
delete cfg.stateStyles;
}
Object.assign(model, cfg);
this.updateShape();
this.afterUpdate();

View File

@ -0,0 +1,196 @@
import React, { useRef, useEffect } from 'react';
import G6 from '../../../src';
import isArray from '@antv/util/lib/is-array';
const data = {
// 点集
nodes: [
{
id: 'node1', // String该节点存在则必须节点的唯一标识
x: 100, // Number可选节点位置的 x 值
y: 200, // Number可选节点位置的 y 值
},
{
id: 'node2', // String该节点存在则必须节点的唯一标识
x: 300, // Number可选节点位置的 x 值
y: 200, // Number可选节点位置的 y 值
},
],
// 边集
edges: [
{
source: 'node1', // String必须起始点 id
target: 'node2', // String必须目标点 id
},
],
};
// import "./styles.css";
/**
*
*
* changeData方法后
*/
export default () => {
const graphContainer = useRef(null);
let graph = null// useRef(null);
// 图初始化
useEffect(() => {
if (!graph) {
graph = new G6.Graph({
container: graphContainer.current, // String | HTMLElement必须在 Step 1 中创建的容器 id 或容器本身
width: 800, // Number必须图的宽度
height: 500, // Number必须图的高度
modes: {
default: [
"drag-canvas",
"zoom-canvas",
"drag-node",
{
type: "brush-select",
trigger: "ctrl",
includeEdges: false,
selectedState: "click"
}
] // 允许拖拽画布、放缩画布、拖拽节点
// default: ["drag-canvas", "zoom-canvas"] // 允许拖拽画布、放缩画布
},
defaultNode: {
size: 50, // 节点大小
style: {
opacity: 0.8,
lineWidth: 1,
stroke: "#999"
},
labelCfg: {
style: {
fill: "#fff"
}
}
},
defaultEdge: {
labelCfg: {
autoRotate: true,
style: {
fontSize: 14,
fill: "#333"
}
},
style: {
stroke: "#808080",
lineWidth: 1,
endArrow: true,
lineAppendWidth: 10,
// opacity: 0.6
}
},
// 节点不同状态下的样式集合
nodeStateStyles: {
// 鼠标 hover 上节点,即 hover 状态为 true 时的样式
hover: {
fill: "lightsteelblue"
},
// 鼠标点击节点,即 click 状态为 true 时的样式
click: {
shadowColor: "#808080",
shadowBlur: 10,
lineWidth: 2,
fill: 'yellow'
// fill: "lightsteelblue"
}
},
// 边不同状态下的样式集合
edgeStateStyles: {
// 鼠标点击边,即 click 状态为 true 时的样式
click: {
stroke: "red",
lineWidth: 2
// shadowColor: "#000",
// shadowBlur: 10
}
},
});
}
graph && graph.data(data);
graph && graph.render();
graph.on("edge:click", e => {
// 先将所有当前是 click 状态的边置为非 click 状态
const edgeItem = e.item; // 获取被点击的边元素对象
graph.setItemState(edgeItem, "click", true); // 设置当前边的 click 状态为 true
// this.options.edgeClickCallback();
});
graph.on("node:click", e => {
// 先将所有当前是 click 状态的节点置为非 click 状态
const nodeItem = e.item; // 获取被点击的节点元素对象
graph.setItemState(nodeItem, "click", true); // 设置当前节点的 click 状态为 true
});
// 鼠标进入节点
graph.on("node:mouseenter", e => {
const nodeItem = e.item; // 获取鼠标进入的节点元素对象
graph.setItemState(nodeItem, "hover", true); // 设置当前节点的 hover 状态为 true
});
graph.on("node:mouseleave", e => {
const nodeItem = e.item; // 获取鼠标离开的节点元素对象
graph.setItemState(nodeItem, "hover", false); // 设置当前节点的 hover 状态为 false
});
}, []);
const toggleEdge = () => {
const clickEdges = graph.findAllByState("edge", "click");
clickEdges.forEach(clickEdge => {
const model = {
style: {
stroke: "#808080",
lineWidth: 1,
endArrow: true,
lineAppendWidth: 10,
},
stateStyles: {
click: {
stroke: "#333",
lineWidth: 2
}
}
};
graph.updateItem(clickEdge, model);
});
};
/**
* node2节点
*/
const toggleNode = () => {
const clickNodes = graph.findAllByState("node", "click");
// console.log(clickNodes);
clickNodes.forEach(clickNode => {
// let model = clickNode.getModel();
// console.log(model);
const model = {
style: {
opacity: 0.8,
lineWidth: 1,
stroke: "green"
},
stateStyles: {
// 修改 hover 状态下的样式
click: {
stroke: 'blue'
}
}
};
graph.updateItem(clickNode, model);
});
};
return (
<div>
<button onClick={toggleNode}></button>
<button onClick={toggleEdge}></button>
<div ref={graphContainer} className={'graph-container'} />
</div>
);
};

View File

@ -8,6 +8,7 @@ import DomClick from './component/dom-click';
import ForceLayout from './forceLayout';
import GGEditorNode from './ggeditorNode';
import MultiLayout from './forceLayout/multiLayout'
import EdgeStatus from './edgeStatus'
export default { title: 'Issues' };
@ -20,3 +21,4 @@ storiesOf('Issues', module)
.add('forcelayout', () => <ForceLayout />)
.add('ggeditor node issue', () => <GGEditorNode />)
.add('multi layout', () => <MultiLayout />)
.add('edge status', () => <EdgeStatus />)

View File

@ -576,4 +576,133 @@ describe('graph edge states', () => {
graph.emit('edge:mouseleave', { item: edge });
graph.destroy();
});
it('update edge states with updateItem', () => {
const data = {
// 点集
nodes: [
{
id: 'node1', // String该节点存在则必须节点的唯一标识
x: 100, // Number可选节点位置的 x 值
y: 200, // Number可选节点位置的 y 值
},
{
id: 'node2', // String该节点存在则必须节点的唯一标识
x: 300, // Number可选节点位置的 x 值
y: 200, // Number可选节点位置的 y 值
},
],
// 边集
edges: [
{
id: 'node1-node2',
source: 'node1', // String必须起始点 id
target: 'node2', // String必须目标点 id
},
],
};
const graph = new G6.Graph({
container: div, // String | HTMLElement必须在 Step 1 中创建的容器 id 或容器本身
width: 800, // Number必须图的宽度
height: 500, // Number必须图的高度
modes: {
default: [
"drag-canvas",
"zoom-canvas",
"drag-node",
{
type: "brush-select",
trigger: "ctrl",
includeEdges: false,
selectedState: "click"
}
]
},
defaultNode: {
size: 50, // 节点大小
style: {
opacity: 0.8,
lineWidth: 1,
stroke: "#999"
},
labelCfg: {
style: {
fill: "#fff"
}
}
},
defaultEdge: {
labelCfg: {
autoRotate: true,
style: {
fontSize: 14,
fill: "#333"
}
},
style: {
stroke: "#808080",
lineWidth: 1,
endArrow: true,
lineAppendWidth: 10,
}
},
// 边不同状态下的样式集合
edgeStateStyles: {
// 鼠标点击边,即 click 状态为 true 时的样式
click: {
stroke: "red",
lineWidth: 2
}
},
});
graph.data(data)
graph.render()
// 验证 edge 的初始样式
const currentEdge = graph.findById('node1-node2')
let states = currentEdge.getStates()
expect(states.length).toBe(0)
let keyShape = currentEdge.getKeyShape()
expect(keyShape.attr('stroke')).toEqual('#808080')
// 先设置 edge click states
graph.setItemState(currentEdge, 'click', true)
states = currentEdge.getStates()
expect(states.length).toBe(1)
let stateStyle = currentEdge.getStateStyle('click')
expect(stateStyle).toEqual({"lineWidth": 2, "stroke": "red"})
keyShape = currentEdge.getKeyShape()
expect(keyShape.attr('stroke')).toEqual('red')
// 验证此时 edge 的样式状态
// 再使用 updateItem 更新 click states
const model = {
style: {
stroke: "#808080",
lineWidth: 1,
endArrow: true,
lineAppendWidth: 10,
},
stateStyles: {
click: {
stroke: "#333",
lineWidth: 2
}
}
};
graph.updateItem('node1-node2', model);
// updateItem 以后edge click states 的值以及变化了
stateStyle = currentEdge.getStateStyle('click')
expect(stateStyle).toEqual({"lineWidth": 2, "stroke": "#333"})
graph.destroy()
expect(graph.destroyed).toBe(true)
})
});