mirror of
https://gitee.com/antv/g6.git
synced 2024-12-15 18:11:08 +08:00
267 lines
9.6 KiB
Markdown
267 lines
9.6 KiB
Markdown
---
|
||
title: Take Use of State Mechanism
|
||
order: 5
|
||
---
|
||
|
||
<span style="background-color: rgb(251, 233, 231); color: rgb(139, 53, 56)"><strong>⚠️ Attention:</strong></span> 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.
|
||
|
||
```javascript
|
||
const graph = new G6.Graph({
|
||
container,
|
||
width,
|
||
height,
|
||
nodeStateStyles: {
|
||
hover: {
|
||
fill: 'red',
|
||
'keyShape-name': {
|
||
fill: 'red',
|
||
},
|
||
},
|
||
},
|
||
edgeStateStyles: {},
|
||
});
|
||
```
|
||
|
||
The state style of [keyShape](/en/docs/manual/middle/elements/shape/shape-keyshape/#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.
|
||
|
||
```javascript
|
||
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](/#global-state) and State for [Single Node/Edge](/#state-for-single-nodeedge). Now we show how to define the global state styles for sub shapes as an example.
|
||
|
||
```javascript
|
||
const graph = new G6.Graph({
|
||
container,
|
||
width,
|
||
height,
|
||
nodeStateStyles: {
|
||
selected: {
|
||
'sub-element': {
|
||
fill: 'green',
|
||
},
|
||
'text-element': {
|
||
stroke: 'red',
|
||
},
|
||
},
|
||
},
|
||
edgeStateStyles: {},
|
||
});
|
||
```
|
||
|
||
In [Global State](/#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.
|
||
|
||
```javascript
|
||
// 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.
|
||
|
||
|
||
<span style="background-color: rgb(251, 233, 231); color: rgb(139, 53, 56)"><strong>⚠️ NOTICE: </strong></span>
|
||
|
||
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` or `false`, 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)`.
|
||
|
||
```javascript
|
||
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.
|
||
|
||
```javascript
|
||
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`.
|
||
|
||
```javascript
|
||
// 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.
|
||
|
||
```javascript
|
||
// 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`.
|
||
|
||
```javascript
|
||
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 calling `updateItem`;
|
||
- The state style to be updated is not active on an item, `item.hasState('hover') === false`: The style will be changed after calling `graph.setItemState(item, 'hover', true)`.
|
||
|
||
### Cancel States
|
||
|
||
`graph.clearItemStates` can be used to cancel one or more states set by `graph.setItemState`.
|
||
|
||
```javascript
|
||
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.:
|
||
|
||
```javascript
|
||
// 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);
|
||
}
|
||
```
|