9.6 KiB
title | order |
---|---|
Take Use of State Mechanism | 5 |
⚠️ Attention: State with multiple values, mutually exclusive state, updating styles for sub shapes are supported after V3.4.
Background
State of item (Node/Edge) build the fast relationships between 「interactions/data changes」 and 「changes of item styles」.
e.g.: the 'hover' state of a node is activated when the mouse enters the node, and the style of the node is changed to response the interaction; 'hover' state is inactivated when the mouse leave the node, and the style of the node is resumed.
In actual scene, state has lots of implicity recommand and complexity.
Challenges
- Configure the target state quickly: Assign a new state and clear all the existing states on a node;
- State with multiple values: e.g. the 'bodyState' of a node representing a person has four values 'healthy', 'suspect', 'ill', and 'dead';
- Mutually exclusive state: e.g. 'healthy', 'suspect', 'ill', and 'dead' for 'bodyState' are mutually exclusive to each other, any two of them will not exist on a person in the same time;
- Update the styles for all the sub shapes on a node or an edge: e.g. a node consist of a rect, a text and a icon image. When the state of the node is chagned, styles of all the shapes can be changed to response it; Modify the state configurations: modify the style configurations for a state easily.
Solution
To address the issues above, we have the following functions for states in G6 3.4:
- Define a state with unified method;
- Set state value with
setItemState
function; - Update state value with
updateItem
function; - Cancel state with
clearItemStates
function.
Define a State
Global State
The global state in G6 is defined by nodeStateStyles
and edgeStateStyles
on the graph instance.
const graph = new G6.Graph({
container,
width,
height,
nodeStateStyles: {
hover: {
fill: 'red',
'keyShape-name': {
fill: 'red',
},
},
},
edgeStateStyles: {},
});
The state style of keyShape can be defined in nodeStateStyles
or edgeStateStyles
directly. You can also define the styles in the object with the key equals to the name
of the keyShape.
State for Single Node/Edge
Expect set the global styles for items(nodes/edges), you can also define different styles for different items by assgin stateStyles
in graph.node(fn)
/ graph.edge(fn)
function.
graph.node((node) => {
return {
...node,
stateStyles: {},
};
});
const data = {
nodes: [
{
id: 'node',
stateStyles: {},
},
],
};
State Styles for Sub-shapes
On the ascpect of drawing, an item(node/edge) has a graphics group, which contains a keyShape and several sub-shapes. Before V3.4, state styles are only available on keyShape, which means users need to define state styles for other sub shapes in setState
function when custom a node or an item type.
G6 3.4 supports state styles for sub shapes. They can also be defined by two ways as Global State and State for Single Node/Edge. Now we show how to define the global state styles for sub shapes as an example.
const graph = new G6.Graph({
container,
width,
height,
nodeStateStyles: {
selected: {
'sub-element': {
fill: 'green',
},
'text-element': {
stroke: 'red',
},
},
},
edgeStateStyles: {},
});
In Global State, we recommand define the keyShape's state styles by an object with key equals to the name
of the keyShape. Similary, you can define the state styles for any sub shape with an object with key equals to its name
.
As the shown in the above code, we define the state styles for two sub shapes with name
s 'sub-element'
and 'text-element'
respectively. When we set the state for an item by calling graph.setItemState(item, 'selected', true)
, the styles of the sub shapes named 'sub-element'
and 'text-element'
will be updated as well.
// Calling the following code, the styles of sub-element and text-element will be changed
graph.setItemState(item, 'selected', true);
Besides, G6 also supports updateItem
function to update the state styles for an item.
⚠️ NOTICE:
The state styles for sub-shapes are only available for the sub-shapes which are the chilren of the root graphics group of a node/edge, but not other descendant shapes grouped by nested sub-graphics-groups. The sub-shapes in the built-in nodes/edges are all the children of the root graphics group of a node/edge. If you are customizing a node/edge type, this rule should be noticed.
Set State
G6 V3.4 supports state with multiple values and binary values:
Binary: the value can be
true
orfalse
, means the state is activated or inactivated respectivly; Multiple value: e.g. a node represents a person with 'bodyState', which has four values: 'healthy', 'suspect', 'ill', 'dead'.
Binary State
Binary state is commonly used in interactions, e.g. hover, selected, etc. When a node is selected, the selected state is activated with true value; the selected state is inactivated with false when the node is deselected.
Set the binary state by calling graph.setItemState(item, 'selected', true)
.
const graph = new G6.Graph({
//...
nodeStateStyles: {
selected: {
fill: 'red',
},
},
});
graph.setItemState(item, 'selected', true);
State with Multiple Values
State with multiple values exists in complex actual cases, e.g. the 'bodyState' of a node representing a person has four values 'healthy', 'suspect', 'ill', and 'dead'. The binary state can not satisfy such situation.
const graph = new Graph({
// ... Other configurations
// The state styles in different states
nodeStateStyles: {
// bodyState with multiple values and matually exclusive
'bodyState:healthy': {
// the state styles for the keyShape
fill: 'green',
},
'bodyState:suspect': {},
'bodyState:ill': {},
},
});
graph.setItemState(item, 'bodyState', 'healthy');
Matually Exclusive State
State with multiple values also solves the matually exclusive problem. We now use the same example as above, bodyState
has four values: healthy
, suspect
, ill
, dead
.
// Matually exclusive state
graph.setItemState(item, 'bodyState', 'healthy');
// Call the following code, the value of bodyState will be changed to dead,
// and item.hasState('bodyState:healthy') will return false
graph.setItemState(item, 'bodyState', 'dead');
After calling the code above, the value of the item's bodyState
is dead
.
Update the Configurations for State Styles
Before V3.3, G6 does not support modification on the configurations for state styles. And updateItem
can only be used to update the default style for keyShape. With V3.4, updateItem
supports updating the default styles and state styles for keyShape and other sub shapes.
Update Default Styles
You can update the default styles for keyShape and sub shapes by assigning the object with the key equals the name
of the sub shape in style
of the updateItem
's second parameter.
// Update item with the default style of keyShape and other sub shapes
graph.updateItem(item, {
style: {
// for keyShape's fill, stroke, and opacity
fill: 'green',
stroke: 'green',
opacity: 0.5,
// the styles for the sub shape named 'node-text'
'node-text': {
stroke: 'yellow',
},
},
});
Update State Styles
updateItem
also can be used to update the state styles for keyShape and sub shapes with stateStyles
.
graph.updateItem(item, {
style: {
stroke: 'green',
'node-text': {
stroke: 'yellow',
},
},
stateStyles: {
hover: {
opacity: 0.1,
'node-text': {
stroke: 'blue',
},
},
},
});
graph.setItemState(item, 'hover', true);
There might be two situations when calling updateItem
:
- The state style to be updated is already activated on an item,
item.hasState('hover') === true
: the style will be changed immediately after callingupdateItem
; - The state style to be updated is not active on an item,
item.hasState('hover') === false
: The style will be changed after callinggraph.setItemState(item, 'hover', true)
.
Cancel States
graph.clearItemStates
can be used to cancel one or more states set by graph.setItemState
.
graph.setItemState(item, 'bodyState', 'healthy');
graph.setItemState(item, 'selected', true);
graph.setItemState(item, 'active', true);
// Cancel a single state
graph.clearItemStates(item, 'selected');
graph.clearItemStates(item, ['selected']);
// Cancel multiple states
graph.clearItemStates(item, ['bodyState:healthy', 'selected', 'active']);
State Priority
G6 does not explicitly provide the state priority mechanism. But the hasState
function which is used to get the value of a state, helps users to control the priority by themselves. e.g.:
// Activate the 'active' state of the item to be true
graph.setItemState(item, 'active', true);
// returns the value of 'active' state
const hasActived = item.hasState('active');
// If the value of 'active' state is false, the 'hover' state can be set to true
if (!hasActived) {
graph.setItemState(item, 'hover', true);
}