|
| 1 | +--- |
| 2 | +title: How to custom node with React Component |
| 3 | +order: 5 |
| 4 | +--- |
| 5 | + |
| 6 | +Customing nodes has long been a problem, and even with the introduction of the jsx solution to simplify it, it's still difficult, so we've introduced `@antv/g6-react-node`, a package that makes it easier to define nodes. event animations, etc., to make it easier to use G6. |
| 7 | + |
| 8 | +### How to use |
| 9 | + |
| 10 | +First of all, after installing G6, you need to additionally install `@antv/g6-react-node` |
| 11 | + |
| 12 | +```bash |
| 13 | +npm install @antv/g6-react-node |
| 14 | +// yarn add @antv/g6-react-node |
| 15 | +``` |
| 16 | + |
| 17 | +As an example of a simple card with definitions, custom events, node data management, etc.. |
| 18 | + |
| 19 | +```jsx |
| 20 | +import React from 'react'; |
| 21 | +import G6 from '@antv/g6'; |
| 22 | +import { Rect, Text, Circle, Image, Group, createNodeFromReact } from '@antv/g6-react-node'; |
| 23 | + |
| 24 | +const Tag = ({ text, color }) => ( |
| 25 | + <Rect |
| 26 | + style={{ |
| 27 | + fill: color, |
| 28 | + padding: [5, 10], |
| 29 | + width: 'auto', |
| 30 | + radius: [4], |
| 31 | + margin: [0, 8], |
| 32 | + }} |
| 33 | + > |
| 34 | + <Text style={{ fill: '#fff', fontSize: 10 }}>{text}</Text> |
| 35 | + </Rect> |
| 36 | +); |
| 37 | + |
| 38 | +const Card = ({ cfg }) => { |
| 39 | + const { collapsed = false } = cfg; |
| 40 | + |
| 41 | + return ( |
| 42 | + <Group draggable> |
| 43 | + <Rect |
| 44 | + style={{ |
| 45 | + width: 400, |
| 46 | + height: 'auto', |
| 47 | + fill: '#fff', |
| 48 | + stroke: '#ddd', |
| 49 | + shadowColor: '#eee', |
| 50 | + shadowBlur: 30, |
| 51 | + radius: [8], |
| 52 | + justifyContent: 'center', |
| 53 | + padding: [18, 0], |
| 54 | + }} |
| 55 | + draggable |
| 56 | + > |
| 57 | + <Text |
| 58 | + style={{ |
| 59 | + fill: '#000', |
| 60 | + margin: [0, 24], |
| 61 | + fontSize: 16, |
| 62 | + fontWeight: 'bold', |
| 63 | + }} |
| 64 | + > |
| 65 | + This is a card |
| 66 | + </Text> |
| 67 | + <Text style={{ fill: '#ccc', fontSize: 12, margin: [12, 24] }}> |
| 68 | + I'm loooooooooooooooooooooooooooooooooog |
| 69 | + </Text> |
| 70 | + {collapsed && ( |
| 71 | + <Group> |
| 72 | + <Image |
| 73 | + style={{ |
| 74 | + img: 'https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg', |
| 75 | + width: 200, |
| 76 | + height: 200, |
| 77 | + margin: [24, 'auto'], |
| 78 | + }} |
| 79 | + /> |
| 80 | + <Rect style={{ width: 'auto', flexDirection: 'row', padding: [4, 12] }}> |
| 81 | + <Tag color="#66ccff" text="We" /> |
| 82 | + <Tag color="#66ccff" text="are" /> |
| 83 | + <Tag color="#66ccff" text="many" /> |
| 84 | + <Tag color="#66ccff" text="tags" /> |
| 85 | + </Rect> |
| 86 | + </Group> |
| 87 | + )} |
| 88 | + <Circle |
| 89 | + style={{ |
| 90 | + position: 'absolute', |
| 91 | + x: 380, |
| 92 | + y: 20, |
| 93 | + r: 5, |
| 94 | + fill: collapsed ? 'blue' : 'green', |
| 95 | + }} |
| 96 | + > |
| 97 | + <Text |
| 98 | + style={{ |
| 99 | + fill: '#fff', |
| 100 | + fontSize: 10, |
| 101 | + margin: [-6, -3, 0], |
| 102 | + cursor: 'pointer', |
| 103 | + }} |
| 104 | + onClick={(evt, node, shape, graph) => { |
| 105 | + graph.updateItem(node, { |
| 106 | + collapsed: !collapsed, |
| 107 | + }); |
| 108 | + }} |
| 109 | + > |
| 110 | + {collapsed ? '-' : '+'} |
| 111 | + </Text> |
| 112 | + </Circle> |
| 113 | + </Rect> |
| 114 | + </Group> |
| 115 | + ); |
| 116 | +}; |
| 117 | + |
| 118 | +G6.registerNode('test', createNodeFromReact(Card)); |
| 119 | +``` |
| 120 | + |
| 121 | +It results in this |
| 122 | + |
| 123 | +<img width="400" src="https://gw.alipayobjects.com/zos/antfincdn/imZMZ8jYKJ/xiazai%252520%2815%29.png" /> |
| 124 | + |
| 125 | + |
| 126 | +### Using Guide |
| 127 | + |
| 128 | +#### Shape React Component |
| 129 | + |
| 130 | +When defining React component nodes, you cannot use any hook or asynchronous fetching logic as node drawing currently needs to be a synchronous process, and it is recommended to put all state as well as data information in the node itself DATA for easier management. In a React component node, all data flow should be: node data -> react component props(cfg) -> node content changes. The component itself needs to be free of any side effects and all changes to the node data should be based on updateItem. |
| 131 | + |
| 132 | + |
| 133 | +#### React inner layouts |
| 134 | + |
| 135 | +If you don't do any positioning or layout, all layouts will follow the normal document flow, top-down. To give you more freedom of layout, React also has internal support for flex layouts, which you can use by manipulating: `alignContent`,`alignItems`,`alignSelf`,`display`,`flex`,`flexBasis`,`flexGrow`,` flexShrink`, `flexDirection`, `flexWrap`, `height`, `width`, `justifyContent`, `margin`, `padding`, `maxHeight`, `maxWidth`, `minHeight`, ` minWidth` which control the internal layout of the node. |
| 136 | + |
| 137 | + |
| 138 | +#### Event handling based on the React component Shape |
| 139 | + |
| 140 | +To make it easier to control nodes, we support event binding to a graph inside a node (event bubbling will be supported in a later version), these event binding functions have uniform parameters: `(evt: the event of G6 itself, node: the node where the event occurs, shape: the Shape where the event occurs, graph: the graph where the event is emitted graph)`, we currently support most of the G6 events: `onClick`, `onDBClick`, `onMouseEnter`, `onMouseMove`, `onMouseOut`, `onMouseOver`, `onMouseLeave`, ` onMouseDown `,`onMouseUp `,`onDragStart `,`onDrag `,`onDragEnd `,`onDragEnter `,`onDragLeave `,`onDragOver `,`onDrop `,`onContextMenu ` |
| 141 | + |
| 142 | +⚠️ Note: After using the event, you need to mount the event on the performed pair of graphs using the function `appenAutoShapeListener(graph)`, which can be derived directly from the `@antv/g6-react-node` package. |
| 143 | + |
| 144 | +#### Simple animations based on React component Shape (alpha) |
| 145 | + |
| 146 | +In order to make it easier to add animations to nodes, we have built in some simple animations to use, hopefully to satisfy the effects of basic interaction. In the first phase we have only introduced six animations for now, the `animation` property is animated when it is set, and the property stops animating when it is empty. |
| 147 | + |
| 148 | +For Example: |
| 149 | + |
| 150 | +```jsx |
| 151 | +<Rect |
| 152 | + style={{ |
| 153 | + width: 400, |
| 154 | + // ... |
| 155 | + }} |
| 156 | + draggable |
| 157 | + animation={ |
| 158 | + animated && { |
| 159 | + animate: 'rubber', // 同时支持 'spin','flash','pulse','tada','bounce' |
| 160 | + repeat: true, |
| 161 | + duration: 2000, |
| 162 | + } |
| 163 | + } |
| 164 | + > |
| 165 | +``` |
| 166 | + |
| 167 | +<img src="https://gw.alipayobjects.com/zos/antfincdn/cXLES5%26w5x/ezgif.com-video-to-gif.gif" /> |
| 168 | + |
| 169 | +### More Help |
| 170 | + |
| 171 | +[G6 React Node Docs](https://dicegraph.github.io/g6-react-node/) |
| 172 | + |
| 173 | + |
| 174 | + |
| 175 | + |
| 176 | + |
| 177 | + |
0 commit comments