需要:
应用react实现相似如下的可视化画拓扑图的界面

剖析

能够看出次要性能点有
1.可视化拖拽组件
2.绘制节点和门路

经查阅,找到了与需要非常靠近的组件

GGEditor

这是由阿里的一位大佬写的开源的可视化图编辑器,能够实现绘制节点和门路的性能,反对罕用快捷键,如ctrl+c,ctrl+v,delete等,成果如下图:
demo地址

应用

简略地介绍完须要的库后,开始应用。

1.创立一个名为demo的react我的项目,为了不便,我将应用typescript语言

npx create-react-app demo --typescript

2.装置GGEditor

npm install gg-editor --save

3.为了不便开发,能够应用热更新插件react-refresh,参考此处
4.首先,删除demo/src目录下不必要的文件

5.画流程图
index.js

import React from 'react';import ReactDOM from 'react-dom';import GGEditor, {Flow} from 'gg-editor';//数据const data = {    nodes: [        {            id: '0', label: '点1', x: 55, y: 55, }, {            id: '1', label: '点2', x: 55, y: 255, }, ], edges: [        {            label: '边1', source: '0', target: '1', }, ],};class App extends React.Component {    render() {        return (            <GGEditor> <Flow style={{ width: 500, height: 500 }} data={data} /> </GGEditor> ); }}ReactDOM.render(<App />, document.getElementById('root'));


6.带命令工具栏

import React from 'react';import ReactDOM from 'react-dom';import GGEditor, {Command, ContextMenu, Flow, constants} from 'gg-editor';import styles from './index.less';import { Icon } from '@ant-design/compatible';import {Divider, Tooltip} from 'antd';import upperFirst from 'lodash/upperFirst';const { EditorCommand } = constants;const IconFont = Icon.createFromIconfontCN({    scriptUrl: 'https://at.alicdn.com/t/font_1518433_oa5sw7ezue.js',});const FLOW_COMMAND_LIST = [    EditorCommand.Undo, EditorCommand.Redo, '|', EditorCommand.Copy, EditorCommand.Paste, EditorCommand.Remove, '|', EditorCommand.ZoomIn, EditorCommand.ZoomOut,];const flowData = {    nodes: [        {            id: '0', label: 'Node', x: 50, y: 50, }, {            id: '1', label: 'Node', x: 50, y: 200, }, ], edges: [        {            label: 'Label', source: '0', sourceAnchor: 1, target: '1', targetAnchor: 0, }, ],};function App() {    return (        <GGEditor> <div className={styles.toolbar}> {FLOW_COMMAND_LIST.map((name, index) => {                    if (name === '|') {                        return <Divider key={index} type="vertical" />; }                    return (                        <Command key={name} name={name} className={styles.command} disabledClassName={styles.commandDisabled}> <Tooltip title={upperFirst(name)}> <IconFont type={`icon-${name}`} /> </Tooltip> </Command> ); })}            </div> <Flow className={styles.graph} data={flowData} /> {/* <Mind className={styles.graph} data={mindData} /> */}            <ContextMenu renderContent={(item, position, hide) => {                    const { x: left, y: top } = position; return (                        <div className={styles.contextMenu} style={{ position: 'absolute', top, left }}> {[EditorCommand.Undo, EditorCommand.Redo, EditorCommand.PasteHere].map(name => {                                return (                                    <Command key={name} name={name} className={styles.command} disabledClassName={styles.commandDisabled}> <div onClick={hide}> <IconFont type={`icon-${name}`} /> <span>{upperFirst(name)}</span> </div> </Command> ); })}                        </div> ); }}            /> </GGEditor> );}ReactDOM.render(<App />, document.getElementById('root'));


7.节点提供栏

import React from 'react';import ReactDOM from 'react-dom';import GGEditor, { Flow, Item, ItemPanel} from 'gg-editor';import styles from './index.less';const data = {    nodes: [        {            id: '0', label: 'Node', x: 50, y: 50, }, {            id: '1', label: 'Node', x: 50, y: 200, }, ], edges: [        {            label: 'Label', source: '0', sourceAnchor: 1, target: '1', targetAnchor: 0, }, ],};function App() {    return (        <GGEditor> <ItemPanel className={styles.itemPanel}> <Item className={styles.item}                    model={{                        type: 'circle', size: 50, label: 'circle', }}                > <img src="https://gw.alicdn.com/tfs/TB1IRuSnRr0gK0jSZFnXXbRRXXa-110-112.png" width="55" height="56" draggable={false}                    /> </Item> <Item className={styles.item}                    model={{                        type: 'rect', size: [80, 24], label: 'rect', }}                > <img src="https://gw.alicdn.com/tfs/TB1reKOnUT1gK0jSZFrXXcNCXXa-178-76.png" width="89" height="38" draggable={false}                    /> </Item> <Item className={styles.item}                    model={{                        type: 'ellipse', size: [100, 50], label: 'ellipse', }}                > <img src="https://gw.alicdn.com/tfs/TB1AvmVnUH1gK0jSZSyXXXtlpXa-216-126.png" width="108" height="63" draggable={false}                    /> </Item> <Item className={styles.item}                    model={{                        type: 'diamond', size: [80, 80], label: 'diamond', }}                > <img src="https://gw.alicdn.com/tfs/TB1EB9VnNz1gK0jSZSgXXavwpXa-178-184.png" width="89" height="92" draggable={false}                    /> </Item> <Item className={styles.item}                    model={{                        type: 'triangle', size: [30, 30], label: 'triangle', }}                > <img src="https://gw.alicdn.com/tfs/TB12sC2nKH2gK0jSZJnXXaT1FXa-126-156.png" width="63" height="78" draggable={false}                    /> </Item> </ItemPanel> <Flow className={styles.graph} data={data} /> </GGEditor> );}ReactDOM.render(<App />, document.getElementById('root'));

然而,但这里就呈现问题了,itempanel画进去的节点并没有能够连贯的锚点,通过检索,找官网文档,发现一大半曾经删除了

github上有人也遇到了和我一样的问题,然而基本没有人回应

直到我在检索到这句话时,所有都明确了

看来官网仿佛也把这个我的项目放弃了,一不小心就踩了一个大坑啊。

总结

这个组件,在官网展现的例子上有十分简洁实用的示例,但在我初步上手后发现文档完好非常重大,遇到问题齐全无奈解决,除非读代码,对react老手及其不敌对,且antv官网仿佛都有放弃的痕迹,非大佬不能应用。