antv-x6-vue
github 地址:antv-x6-vue
核心思想
- 因为 x6 次要面向编辑场景,所以对每一个节点有更多的交互逻辑。所以,将 x6 的 Shape 形象成组件,每一个组件负责管理本人的生命周期。
-
针对简单的自定义图形,利用 x6 反对渲染 vue 组件 @antv/x6-vue-shape 的性能,同时利用 slots 将节点渲染交给以后组件,将图形相干逻辑交给 x6。
import {VueShape as VueShapeContainer} from '@antv/x6-vue-shape'; cell.value = new VueShapeContainer({ id, width, height, primer, useForeignObject, // 这里将本人的 slots 中的内容强行放到画布中去 // 这样图构造的交互还有一些操作逻辑交给 x6 // 通过 vue 绘制的组件渲染和组件外部交互逻辑交给用户 component: component ? component : () => h('div', {key: id, class: 'vue-shape'}, slots.default ? slots.default({props, item: cell}) : null), ...otherOptions, }) graph.addCell(cell.value)
- 提供
useVueShape
,能够很容易的自定义一个 vue 组件定制进去的节点。 -
提供
useCellEvent
,能够比拟不便的给以后节点绑定事件。const CustomNode = defineComponent({ name: 'CustomNode', props: [...VueShapeProps, 'otherOptions'], inject: [contextSymbol], setup(props, context) { // 间接传递 props 给 useVueShape,watch 的时候不能监听到变动 const cell = useVueShape(() => props, context) useCellEvent('node:click', (e) => context.emit('click', e), {cell}) return () => null} })
- 提供
useTeleport
,优化x6-vue-shape
默认创立多个 App 导致渲染性能问题。同时避免出现节点数据更新不及时问题。
装置
yarn add antv-x6-vue
Components
- [x] 提供
Graph
容器以及GraphContext.useContext
获取x6
的graph
对象。能够利用这个对象操作画布,绑定事件。 - [x] 包装
Shape
作为vue
组件+应用x6-vue-shape
封装自定义组件,裸露的组件有:
类 | shape 名称 | 形容 |
---|---|---|
Node | rect | 等同于 Shape.Rect |
Edge | edge | 等同于 Shape.Edge |
VueShape | vue-shape | 应用 @antv/x6-vue-shape 渲染的自定义 vue 组件的容器,能够将 slots.default 内容渲染到节点内。 |
Shape.Rect | rect | 矩形。 |
Shape.Circle | circle | 圆形。 |
Shape.Ellipse | ellipse | 椭圆。 |
Shape.Polygon | polygon | 多边形。 |
Shape.Polyline | polyline | 折线。 |
Shape.Path | path | 门路。 |
Shape.Image | image | 图片。 |
Shape.HTML | html | HTML 节点,应用 foreignObject 渲染 HTML 片段。 |
Shape.TextBlock | text-block | 文本节点,应用 foreignObject 渲染文本。 |
Shape.BorderedImage | image-bordered | 带边框的图片。 |
Shape.EmbeddedImage | image-embedded | 内嵌入矩形的图片。 |
Shape.InscribedImage | image-inscribed | 内嵌入椭圆的图片。 |
Shape.Cylinder | cylinder | 圆柱。 |
Shape.Edge | edge | 边。 |
Shape.DoubleEdge | double-edge | 双线边。 |
Shape.ShadowEdge | shadow-edge | 暗影边。 |
另外提供帮忙函数
名称 | 形容 |
---|---|
useCell | 应用这个函数能够通过传递 markup 之类的参数自定义节点 |
useVueShape | 应用这个函数自定义 vue 的渲染内容定制更加简单的节点 |
useCellEvent | 通过这个函数绑定事件到 cell 下面 |
- [x] 形象连贯桩为组件应用
名称 | 形容 |
---|---|
PortGroup | 提供 ports/groups/<group_name> 相干的配置,同时也作为 Port 组件的容器,提供一个默认的 group 名称 |
Port | 调用 addPort/removePort 操作以后连贯桩,比 x6 官网多提供一个 magnet 参数(默认状况须要应用 attrs/circle/magnet 进行配置)。另外,Port 也能够独立应用。 |
应用 Port 和 PortGroup 的时候,能够放在一个以
port
命名的 slot 外面(思考到默认的 VueShape 会将默认的 slot 认为是用户自定义的节点,这里应用 slots.port 辨别一下),也能够间接应用默认的 slot
<Node id="1" :x="100" :y="100" label="node1">
<PortGroup name="in" position="top" :attrs="{circle: {r: 6, magnet: true, stroke:'#31d0c6'}}">
<Port id="id1" />
<Port id="id2" :magnet="false" />
</PortGroup>
</Node>
<Node id="2" :x="200" :y="200" label="node2">
<Port id="id1" />
</Node>
- [x] 提供内置的一些组件
名称 | 形容 |
---|---|
Grid | 渲染网格 |
Background | 渲染背景 |
Scroller | 滚动组件 |
Clipboard | 剪贴板,配合 Keyboard 组件能够应用ctrl+c /ctrl+x /ctrl+v |
Keyboard | 键盘快捷键 |
MouseWheel | 鼠标滚轮,反对应用滚轮实现画布放大放大 |
Connecting | 配置连线相干参数和帮忙办法 |
- [x] Widgets
名称 | 形容 |
---|---|
Snapline | 对齐线 |
Selection | 点选 / 框选 |
MiniMap | 小地图 |
Stencil | 内置的带分组和搜寻性能的拖拽组件,还提供 StencilGroup 以实现分组性能 |
Contextmenu | 右键菜单 |
TeleportContainer | 一个默认和 useVueShape 绑定到同一个 view 的容器,应用这个组件的时候,能够不必手动调用 useTeleport,也不必专门指定 view |
TODO
- [] Stencil 反对默认分组(不应用
StencilGroup
的状况) - [] Dnd 也作为组件实现
- [x] ContextMenu:实现一个默认的 menu,同时裸露一个 useContextMenu 不便用户定制
- [x] 实现 Connecting,也作为组件应用
-
[x] 提供 PluginInstallFunction,反对全局注册组件(组件有
x6-
或者X6
前缀,例如X6Node
,x6-node
都会对应后面提到的Node
组件)<x6-node id="44" :x="400" :y="300" label="node4"> <x6-port-group name="in" position="top" :attrs="{circle: {r: 6, magnet: true, stroke:'#31d0c6'}}"> <x6-port id="id1" /> </x6-port-group> </x6-node>
-
[x] 反对群组性能。UI 嵌套的时候主动调用 embed 和 unembed 函数解决父子关系
<Node id="9" :x="500" :y="200" label="node9" :width="300" :height="200"> <Node id="99" :x="550" :y="220" label="node99" :width="200" :height="150"> <Node id="999" :x="580" :y="240" label="node999"></Node> </Node> </Node>
-
[x] 应用 Teleport 渲染
默认的
x6-vue-shape
把每一个节点渲染成一个 vue 的 app 导致渲染性能问题
通过 vue3 提供的 Teleport 性能,让以后 App 的子组件渲染到 foreignobject 外部。解决性能问题的同时,也能更好的解决 VueShape 组件外部数据及时更新的问题
DEMO
import {defineComponent, reactive} from 'vue'
import Graph, {Node, Edge, Grid, Background} from 'antv-x6-vue'
export default defineComponent({setup(props) {
// ...
const state = reactive({
showGrid: true,
y: 10,
visible: true,
})
const methods = {added(e) {console.log('added', e)
},
click(e) {console.log('click', e)
},
changed(e) {console.log('changed', e)
},
}
return {...toRefs(state), ...methods }
},
})
// template
<template>
<Graph>
<Node id="1" :x="100" :y="100" />
<Node id="2" :x="200" :y="200" />
<Edge id="e1" source="1" target="2" />
<VueShape primer="rect" id="3" :x="200" :y="300" :width="160" :attrs="{rect: {fill:'#ddd', stroke:'#333'}, label: {text:'VueShape'}}">
<div> 这里是一个 vue 的组件 </div>
<img style="width: 30px;height:30px;" src="https://v3.cn.vuejs.org/logo.png" />
</VueShape>
<CustomNode
v-if="visible"
primer="circle"
id="4"
:x="400" :y="y"
:attrs="{circle: {fill:'#ddd', stroke:'#333'}, label: {text:'CustomNode'}}"
@added="added"
@click="click"
@cell:change:position="changed"
>
<span>Hello</span>
</CustomNode>
<Edge id="e2" source="1" target="3" />
<Background />
<Grid :visible="showGrid" />
<Snapline />
<Selection />
<Clipboard />
</Graph>
</template>