基于 G6 和 React 的可视化图编辑器
GGEditor - Flow的简单使用
import GGEditor, { Flow } from 'gg-editor';
const data = {
nodes: [{
type: 'node',
size: '70*70',
shape: 'flow-circle',
color: '#FA8C16',
label: '起止节点',
x: 55,
y: 55,
id: 'ea1184e8',
index: 0,
}, {
type: 'node',
size: '70*70',
shape: 'flow-circle',
color: '#FA8C16',
label: '结束节点',
x: 55,
y: 255,
id: '481fbb1a',
index: 2,
}],
edges: [{
source: 'ea1184e8',
sourceAnchor: 2,
target: '481fbb1a',
targetAnchor: 0,
id: '7989ac70',
index: 1,
}],
};
<GGEditor>
<Flow style={{ width: 500, height: 500 }} data={data} />
</GGEditor>
GGEditor是容器组件。所有gg-editor定义的组件要在GGEditor内部才生效。在GGEditor组件上可以挂载两个事件:onBeforeCommandExecute和onAfterCommandExecute。
onBeforeCommandExecute和onAfterCommandExecute内部可以接收一个对象,这个对象包含一个command对象。command对象包含了一些操作方法,例如撤回上一步(back),执行命令(execute)。等等。
Flow组件在GGEditor组件内部被使用,是流程图组件。data接收一个对象,包含节点和连线的信息,初始化一个流程图。data中nodes代表节点,edges代表连线,他们分别以数组的形式记录图形的特征。Flow上可以添加一系列图例事件和鼠标事件,如果在绘图过程中需要处理数据可以在这里进行。
Props API
import { withPropsAPI } from 'gg-editor';
class Component extends React.Component {
componentDidMount() {
const { propsAPI } = this.props;
console.log(propsAPI);
}
}
export default withPropsAPI(Component);
经过 withPropsAPI
包装的组件将会自带 propsAPI
属性。需要注意的是被装饰的组件也必须是在GGEditor的子组件(不能用在GGEditor上)。
属性
说明
类型
executeCommand
执行命令
function(command)
read
读取数据
function(data)
save
保存数据
function() => object
add
添加图项
function(type, model)
find
查找图项
function(id)
update
更新图项
function(item, model)
remove
删除图项
function(item)
getSelected
获取当前选中图项
function
通过propsAPI调用的方法是操作图例的正确方法(之前以为data是可以setState更改的我...)。
Command
下面是所有关于flow组件的内置命令。通过propsAPI.executeCommand()可以调用下面的命令操作图例。
命令英文名
命令中文名
快捷键(Mac)
快捷键(Win)
适用页面
clear
清空画布
-
-
All
selectAll
全选
⌘A
Ctrl+A
All
undo
撤销
⌘Z
Ctrl + Z
All
redo
重做
⇧⌘Z
Shift + Ctrl + Z
All
delete
删除
Delete
Delete
All
zoomIn
放大
⌘=
Ctrl + =
All
zoomOut
缩小
⌘-
Ctrl + -
All
autoZoom
自适应尺寸
-
-
All
resetZoom
实际尺寸
⌘0
Ctrl + 0
All
toFront
提升层级
-
-
All
toBack
下降层级
-
-
All
copy
复制
⌘C
Ctrl + C
Flow
paste
粘贴
⌘V
Ctrl + V
Flow
multiSelect
多选模式
-
-
Flow
addGroup
成组
⌘G
Ctrl + G
Flow
unGroup
取消组
⇧⌘G
Shift + Ctrl + G
Flow
工具栏和图例右击操作,可以通过配置command自由组合。
import GGEditor, { Flow, Command, Toolbar, ContextMenu } from 'gg-editor';
<GGEditor>
<Flow />
<Toolbar>
<Command name="undo"><button>Undo</button></Command>
<Command name="redo">Redo</Command>
</Toolbar>
<ContextMenu>
<Command name="undo">Undo</Command>
<Command name="redo">Redo</Command>
</ContextMenu>
</GGEditor>
ContextMenu下面还有NodeMenu,EdgeMenu,CanvasMenu分组可以选择性的引入。分别对应对节点右击命令、连线右击命令和空白画布右击命令设置。
当然也可以自定义命令。
import GGEditor, { Flow, RegisterCommand } from 'gg-editor';
<GGEditor>
<Flow />
<RegisterCommand name={...} config={...} extend={...} />
</GGEditor>
其中name表示命令名称配置,extend可以继承内置命令。
config可配置自定义命令的各项指标,是否可以进入队列,正反向执行命令函数等。
import React from "react";
import { RegisterCommand, withPropsAPI } from "gg-editor";
class DustomCommand extends React.Component {
render() {
const { propsAPI } = this.props;
const { save, update, getSelected } = propsAPI;
const config = {
// 是否进入列队,默认为 true
queue: true,
// 命令是否可用
enable(/* editor */) {
return true;
},
// 正向命令逻辑
execute(/* editor */) {
// console.log(propsAPI.editor);
const chart = save();
console.log("chart", chart);
const selectedNodes = getSelected();
selectedNodes.map(node => {
update(node, { x: node.model.x + 2, y: node.model.y });
});
},
// 反向命令逻辑
back(/* editor */) {
console.log("执行反向命令2");
},
// 快捷按键配置
shortcutCodes: [["ArrowLeft"], ["ArrowRight"]]
};
return <RegisterCommand name="dustomCommand" config={config} />;
}
}
export default withPropsAPI(DustomCommand);
这段代码从codesandbox复制过来的。用以参考。
ItemPanel
<ItemPanel className={styles.itemPanel}>
<Item
type="node"
size="72*72"
shape="flow-circle"
model={{
color: '#FA8C16',
label: 'Start',
}}
// src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODAiIGhlaWdodD0iODAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxkZWZzPjxjaXJjbGUgaWQ9ImIiIGN4PSIzNiIgY3k9IjM2IiByPSIzNiIvPjxmaWx0ZXIgeD0iLTkuNyUiIHk9Ii02LjklIiB3aWR0aD0iMTE5LjQlIiBoZWlnaHQ9IjExOS40JSIgZmlsdGVyVW5pdHM9Im9iamVjdEJvdW5kaW5nQm94IiBpZD0iYSI+PGZlT2Zmc2V0IGR5PSIyIiBpbj0iU291cmNlQWxwaGEiIHJlc3VsdD0ic2hhZG93T2Zmc2V0T3V0ZXIxIi8+PGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iMiIgaW49InNoYWRvd09mZnNldE91dGVyMSIgcmVzdWx0PSJzaGFkb3dCbHVyT3V0ZXIxIi8+PGZlQ29tcG9zaXRlIGluPSJzaGFkb3dCbHVyT3V0ZXIxIiBpbjI9IlNvdXJjZUFscGhhIiBvcGVyYXRvcj0ib3V0IiByZXN1bHQ9InNoYWRvd0JsdXJPdXRlcjEiLz48ZmVDb2xvck1hdHJpeCB2YWx1ZXM9IjAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAuMDQgMCIgaW49InNoYWRvd0JsdXJPdXRlcjEiLz48L2ZpbHRlcj48L2RlZnM+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg0IDIpIj48dXNlIGZpbGw9IiMwMDAiIGZpbHRlcj0idXJsKCNhKSIgeGxpbms6aHJlZj0iI2IiLz48dXNlIGZpbGwtb3BhY2l0eT0iLjkyIiBmaWxsPSIjRkZGMkU4IiB4bGluazpocmVmPSIjYiIvPjxjaXJjbGUgc3Ryb2tlPSIjRkZDMDY5IiBjeD0iMzYiIGN5PSIzNiIgcj0iMzUuNSIvPjwvZz48dGV4dCBmb250LWZhbWlseT0iUGluZ0ZhbmdTQy1SZWd1bGFyLCBQaW5nRmFuZyBTQyIgZm9udC1zaXplPSIxMiIgZmlsbD0iIzAwMCIgZmlsbC1vcGFjaXR5PSIuNjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQgMikiPjx0c3BhbiB4PSIyMyIgeT0iNDEiPlN0YXJ0PC90c3Bhbj48L3RleHQ+PC9nPjwvc3ZnPg=="
>
flow-circle
</Item>
</ItemPanel>
可以拖拽图形到界面上。ItemPanel作为容器组件,包含Item组件。每个Item拖拽元素上包含了图形和数据信息。如果需要被拖拽的元素上包含数据信息,挂载在Item的model属性中。其中src属性是元素预览,可以不配置,在Item中间用文字表述当前内容。
其他
Minimap: 小地图组件
当初遇到的问题
1.propsAPI获取不到内容:withPropsAPI包裹的组件必须是GGEditor的子组件。
2.自定义组件如何使用:正确的办法是通过config配置,参照上面的代码(之前我在在内部RegisterCommand以后,在onAfterExecuteCommand中截获命令,通过函数控制图例操作。这中间需要下钻到内部组件调用propsAPI,我就通过setState去设置状态传递到子组件。)
3.如何设置拖拽组件:太羞耻了,居然不晓得在Item双标签内放名称。
4.操作流程图后获取数据延迟:如果获取数据有延迟,尝试使用setTimeout,时间间隔设为0后再调propsAPI属性的方法操作。