关于vue3:vue封装x6为原生组件

antv-x6-vue

github地址: antv-x6-vue

核心思想

  1. 因为x6次要面向编辑场景,所以对每一个节点有更多的交互逻辑。所以,将x6的Shape形象成组件,每一个组件负责管理本人的生命周期。
  2. 针对简单的自定义图形,利用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)
    

  1. 提供useVueShape,能够很容易的自定义一个vue组件定制进去的节点。
  2. 提供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
      }
    })
  3. 提供useTeleport,优化x6-vue-shape默认创立多个App导致渲染性能问题。同时避免出现节点数据更新不及时问题。

装置

yarn add antv-x6-vue

Components

  • [x] 提供Graph容器以及GraphContext.useContext获取x6graph对象。能够利用这个对象操作画布,绑定事件。
  • [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>

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理