Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
369f252
fix: (iadd demon prorogress)
liaodalin19903 Mar 31, 2025
7bcf2e1
fix: docs/update-custom-react-node
liaodalin19903 Mar 31, 2025
34fcdfd
fix: 修复Fisheye在update时,未更新this.r/this.d (#6956)
k644606347 Mar 31, 2025
bf0cc01
docs: update antv-dagre layout document (#6958)
chiga0 Apr 1, 2025
3e9c69e
docs: 改造Fisheye插件文档 (#6960)
k644606347 Apr 1, 2025
a5ae240
docs: 优化Watermark水印的文档 (#6963)
k644606347 Apr 1, 2025
8254624
docs: update antv-dagre layout document (#6965)
chiga0 Apr 1, 2025
888d6a7
docs(CreateEdge): 改造文档 [交互 - 内置交互 - CreateEdge 创建边] (#6962)
avrinfly Apr 3, 2025
a38f140
chore(site): optimize ssr in production env (#6970)
yvonneyx Apr 3, 2025
099752c
docs: update theme overview and custom theme docs (#6939)
yvonneyx Apr 3, 2025
39f034a
chore: pin dumi version to 2.4.17 (#6973)
yvonneyx Apr 3, 2025
f372054
fix: (iadd demon prorogress)
liaodalin19903 Mar 31, 2025
770244c
fix: docs/update-custom-react-node
liaodalin19903 Mar 31, 2025
5dd7d57
fix: docs/update-custom-node-react
liaodalin19903 Apr 3, 2025
a606a37
fix: solve the confict
liaodalin19903 Apr 3, 2025
8d529c8
fix: EdgeFilterLens在触发update时,options.r未赋值给this.r,导致配置未生效;fix: style …
k644606347 Apr 9, 2025
31ea481
fix: fix g6-ssr (#6984)
Aarebecca Apr 9, 2025
a1cf3e9
feat(g6-extension-react): react 19 compatibility support (#6972)
yvonneyx Apr 9, 2025
10ee238
docs: 优化EdgeFilterLens边过滤镜文档,更新中英文手册内容 (#6975)
k644606347 Apr 9, 2025
b9b9626
chore: update version (#6985)
yvonneyx Apr 9, 2025
368316c
docs: update demo links from Codesandbox to Stackblitz (#7000)
yvonneyx Apr 9, 2025
d43591e
fix: 更新fisheye demo里的style属性,与缩略图保持一致 (#7001)
k644606347 Apr 9, 2025
ad0ec66
fix: docs/update-custom-node-react
liaodalin19903 Apr 10, 2025
a399007
fix: (iadd demon prorogress)
liaodalin19903 Mar 31, 2025
4d791c5
fix: docs/update-custom-react-node
liaodalin19903 Mar 31, 2025
83b5d5c
fix: docs/update-custom-node-react
liaodalin19903 Apr 3, 2025
963b8d7
fix: docs/update-custom-node-react rebase origin/v5
liaodalin19903 Apr 10, 2025
e95b6ab
Merge branch 'docs/update-custom-node-react' of https://github.com/li…
liaodalin19903 Apr 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions packages/site/docs/manual/element/node/react-node.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,117 @@
title: 使用 React 定义节点
order: 5
---

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

目前不支持 GNode 只支持 React Node,可以关注介绍 React Node 相关内容。

给一些小 tips 来完善这篇文档,可以把以下方面讲清楚:

  1. 介绍(g6-extension-react是什么,优劣势)
  2. 准备工作(环境要求、安装依赖、项目配置)
  3. 使用(引入方式和注册、创建一个 React 组件、使用节点)
  4. 节点状态管理(说明如何将 G6 的节点状态传递给 React 组件,组件内部如何响应)
  5. 交互事件(如何在 React 组件内部处理事件)

## 简介

在数据可视化领域,为高效率使用 AntV G6,节点定义可采用 React 组件的方式。AntV G6 功能强大但原生节点定义处理复杂交互和状态管理有挑战。

### ReactNode 和 GNode 方式自定义 G6 节点

#### ReactNode<span class="label">推荐</span>

React Node 是指借助 React 框架来定义 G6 节点。
这种方式能把 React 组件的优势发挥到极致。React 以组件化开发闻名,使用 React 定义节点可提升代码复用性,减少重复工作,提高开发效率。其强大的状态管理能力便于处理节点的各种交互状态,比如点击、悬停、拖拽等,能让节点交互体验更加流畅。并且 React 拥有庞大的生态系统,有丰富的工具和库可供使用,能轻松为节点添加复杂的样式和交互逻辑,满足多样化的业务需求。

#### GNode

G Node 是基于 G 图形库来定义 G6 节点。
G 是一个高性能的图形渲染引擎,在 G6 中使用 G 来定义节点,能实现高效的图形渲染。G 提供了丰富的图形绘制 API,可直接对节点的图形元素进行精细控制,例如绘制复杂的几何形状、设置样式等。这种方式更侧重于底层的图形操作,在需要对节点图形进行高度定制化时具有很大优势,能够满足对节点外观和性能有严格要求的场景。

### 使用React自定义节点优势

React 组件化、状态管理能力强,将其用于 AntV G6 节点定义,能结合二者优势。可进行组件复用,提升开发效率;轻松处理节点交互状态,优化用户体验。

- 提高开发效率:React 以组件化开发著称,这使得节点定义可以复用。对于相同类型的节点,只需创建一次组件,就能在不同地方重复使用,减少了重复代码的编写,极大地提高了开发效率。
- 增强可维护性:组件化结构使代码逻辑更加清晰,每个组件都有明确的职责。当需要修改某个节点的样式或功能时,只需找到对应的组件进行修改,不会影响到其他部分的代码,降低了维护成本。
- 便于状态管理:React 拥有强大的状态管理能力,能轻松处理节点的各种交互状态,如点击、拖拽、悬停等。通过状态的变化,实时更新节点的显示效果,为用户带来流畅的交互体验。
- 丰富的生态系统:React 拥有庞大的生态系统,有大量可用的工具和库。可以将这些工具和库与 AntV G6 结合使用,为节点添加更多的功能,如动画效果、数据可视化等,满足复杂的业务需求。
- 易于集成:React 作为前端开发的主流框架,与其他前端技术和工具的集成非常方便。可以将使用 React 定义的 AntV G6 节点轻松集成到现有的项目中,与其他组件协同工作,提高项目的整体开发效率。

## 使用步骤

### 安装

```bash
npm install @antv/g6-extension-react
```

### 自定义React节点

ReactNode方式

```jsx
import { ReactNode } from '@antv/g6-extension-react';

const MyReactNode = () => {
return <div>node</div>;
};
```

GNode方式

```jsx
import { Group, Rect, Text } from '@antv/g6-extension-react';

const GNode = () => {
return <Group>
<Rect width={100} height={100}></Rect>
<Text text={"node"} />
<Group>
};
```

### 注册节点

```jsx
import { ExtensionCategory, register } from '@antv/g6';
import { ReactNode } from '@antv/g6-extension-react';

register(ExtensionCategory.NODE, 'react', ReactNode);
```

### 使用节点

使用自定义的ReactNode节点:

```jsx
const graph = new Graph({
// ... other options
node: {
type: 'react',
style: {
component: () => <ReactNode />,
},
},
});
```

使用自定义的GNode节点:

```jsx
const graph = new Graph({
// ... other options
node: {
type: 'g',
style: {
component: () => <GNode />,
},
},
});
```

## 在线测试

<div>
<Playground path="element/custom-node/demo/react-node.jsx" rid="react-node-rid"></Playground>
<Playground path="element/custom-node/demo/reactnode-idcard.jsx" rid="reactnode-idcard"></Playground>
</div>

<style>
.label {
background-color:rgb(255, 168, 168);
padding: 2px 5px;
border-radius: 3px;
font-size: 10px;
}
</style>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里的样式可以通过 insertCss 直接加到对应的示例中

8 changes: 8 additions & 0 deletions packages/site/examples/element/custom-node/demo/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@
"en": "G2 activity Chart"
},
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*GVyoQKk2WIIAAAAAAAAAAAAADmJ7AQ/original"
},
{
"filename": "reactnode-idcard.jsx",
"title": {
"zh": "React 节点 身份证",
"en": "React node IDCard"
},
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*GVyoQKk2WIIAAAAAAAAAAAAADmJ7AQ/original"
}
]
}
133 changes: 133 additions & 0 deletions packages/site/examples/element/custom-node/demo/reactnode-idcard.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// reactnode-idcard.jsx
import React, { useEffect, useRef, useState } from 'react';
import { createRoot } from 'react-dom/client';
import { Graph } from '@antv/g6';
import { ExtensionCategory, register } from '@antv/g6';
import { ReactNode } from '@antv/g6-extension-react';
import { Card, Typography, Button } from 'antd';

const { Title, Text } = Typography;

// 定义自定义节点组件
const IDCardNode = ({ id, data }) => {
const { name, idNumber, address, expanded, graph } = data;
const [isExpanded, setIsExpanded] = useState(expanded || false);

const toggleExpand = () => {
setIsExpanded(!isExpanded);
graph.updateNodeData([{
id,
data: {
...data,
expanded: !isExpanded,
},
}]);
};

console.log('IDCardNode props:', id, data);

return (
<Card
title={
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%' }}>
<Title level={5} style={{ margin: 0 }}>
{name}
</Title>
<Button type="link" onClick={toggleExpand} style={{ padding: 0 }}>
{isExpanded ? 'fold' : 'expand'}
</Button>
</div>
}
style={{
width: 250,
padding: 10,
borderColor: '#ddd',
}}
>
{isExpanded ? (
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center' }}>
<Text strong>ID Number:</Text>
<Text>{idNumber}</Text>
<Text strong>Address:</Text>
<Text>{address}</Text>
</div>
) : (
<Text style={{ textAlign: 'center' }}>IDCard Information</Text>
)}
</Card>
);
};

// 注册自定义节点
register(ExtensionCategory.NODE, 'id-card', ReactNode);

// 定义 Graph 数据
const data = {
nodes: [
{
id: 'node1',
data: {
name: 'Alice',
idNumber: 'IDUSAASD2131734',
address: '1234 Broadway, Apt 5B, New York, NY 10001',
expanded: false, // 初始状态为收缩
},
style: { x: 50, y: 50 },
},
{
id: 'node2',
data: {
name: 'Bob',
idNumber: 'IDUSAASD1431920',
address: '3030 Chestnut St, Philadelphia, PA 19104',
expanded: false, // 初始状态为收缩
},
style: { x: 500, y: 100 },
},
],
edges: [
{
source: 'node1',
target: 'node2',
},
],
};

export const ReactNodeDemo = () => {
const containerRef = useRef();
const graphRef = useRef(null);

useEffect(() => {
// 创建 Graph 实例
const graph = new Graph({
container: containerRef.current,
width: 800,
height: 600,
data,
node: {
type: 'react',
style: {
size: [250, 120], // 调整大小以适应内容
component: (data) => <IDCardNode id={data.id} data={{ ...data.data, graph: graph }} />,
},
},
behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],
});

// 渲染 Graph
graph.render();

// 保存 graph 实例
graphRef.current = graph;

return () => {
graph.destroy();
};
}, []);

return <div style={{ width: '100%', height: '100%' }} ref={containerRef}></div>;
};

// 渲染 React 组件到 DOM
const root = createRoot(document.getElementById('container'));
root.render(<ReactNodeDemo />);
Loading