react+antvX6 制作可编辑图表3——Stencil

3,741 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

项目需求: 最近有一个项目是电路的模拟实验平台,需求为需要有一个工作画布,和一个组件库,实现组件器械的可拖拽、可连接,实验状态可以控制,数据流向展示等功能。就像我们平时课上的虚拟仿真平台一样,又需要像流程图软件一样,可以托拽各种组件到画布中。最后我选择使用antv的X6来制作。

前清提要: 上一期我们讲了antv-X6中的拖拽组件Dnd,这一期我们讲一讲拖拽组件Stencil(详细内容可以参考官方文档)。

Stencil

image.png

Step 1 初始化

下载antv/x6后引入Addon。

import { Addon } from '@antv/x6'
const { Stencil } = Addon;
//const stencil = new Addon.Stencil(options)

同样需要绑定容器。

  refStencil = (container) => {
    this.stencilContainer = container;
  };
<div className="app-stencil" ref={this.refStencil} />

创建实例时,const stencil = new Addon.Stencil(options),在options内你可以定制一些属性,包括 Dnd 的选项和以下选项。

选项类型必选默认值说明
options.titlestring'Stencil'
options.groupsGroup[]✓️分组信息。
options.searchFilterfalse搜索选项。
options.placeholderstring'Search'搜索文本框的 placeholder 文本。
options.notFoundTextstring'No matches found'未匹配到搜索结果时的提示文本。
options.collapsablebooleanfalse是否显示全局折叠/展开按钮。
options.layout(this: Stencil, model: Model, group?: Groupnull) => any网格布局模板画布中节点的布局方法。
options.layoutOptionsany布局选项。
options.stencilGraphWidthnumber200模板画布宽度。
options.stencilGraphHeightnumber800模板画布高度。
options.stencilGraphPaddingnumber10模板画布边距。
options.stencilGraphOptionsGraph.Options

创建stencil时直接使用一个花括号,在其内部配置属性名和属性值。其中是必不可少的是:target:目标画布,绑定之前创建的graph画布即可;groups:分组信息,每个分组中加入一些组件。初始化时,按照 options.groups 提供的分组,在每个分组中会渲染一个模板画布。具体写法如下所示:

 const stencil = new Stencil({
      title: '组件',  //组件名
      target: graph,  //目标画布
      search(cell, keyword) {
        return cell.shape.indexOf(keyword) !== -1;
      },   //搜索框
      placeholder: 'Search by shape name',
      notFoundText: 'Not Found',
      collapsable: true,
      stencilGraphWidth: 250 * rate,
      stencilGraphHeight: 250 * rate,
      groups: [  //2个分组
        {
          name: 'group1',
          title: '常用组件',
          layoutOptions: {
            rowHeight: 100 * rate
          }
        },
        {
          name: 'group2',
          title: '特殊组件',
          // collapsable: false
          layoutOptions: {
            rowHeight: 100 * rate
          }
        }
      ], 
      getDropNode(node) {
        const { width, height } = node.size();
        // 返回一个新的节点作为实际放置到画布上的节点,我返回的是原来组件的克隆,也就是拖拽出来的跟原来的是一样的。
        return node.clone().size(width, height);
      }
    });

Step 2 挂载到页面

//将创建的实例添加到容器中
   this.stencilContainer.appendChild(stencil.container);

Step 3 装载模板节点

在每个分组中都渲染了一个模板画布,接下来我们需要向这些模板画布中添加一些模板节点。

// 创建一些模板节点。
const r1 = new Rect(...)
const c1 = new Circle(...)
const r2 = new Rect(...)
const c2 = new Circle(...)
const r3 = new Rect(...)
const c3 = new Circle(...)

// 将模板节点添加到指定的群组中。
stencil.load([r1, c1, c2, r2.clone()], 'group1')
stencil.load([c2.clone(), r2, r3, c3], 'group2')

添加节点时,使用分组或全局的 layout 和 layoutOptions 来对节点进行自动布局,默认使用网格布局方法来布局模板节点,支持的布局选项有:

选项类型默认值说明
columnsnumber2网格布局的列数,默认为 2。行数根据节点数自动计算。
columnWidthnumber'auto''compact''auto'列宽。auto: 所有节点中最宽节点的宽度作为列宽,compact: 该列中最宽节点的宽度作为列宽。
rowHeightnumber'auto''compact''auto'行高。auto: 所有节点中最高节点的高度作为行高,compact: 该行中最高节点的高度作为行高。
dxnumber10单元格在 X 轴的偏移量,默认为 10
dynumber10单元格在 Y 轴的偏移量,默认为 10
marginXnumber0单元格在 X 轴的边距,默认为 0
marginYnumber0单元格在 Y 轴的边距,默认为 0
centerbooleantrue节点是否与网格居中对齐,默认为 true
resizeToFitbooleanfalse是否自动调整节点的大小来适应网格大小,默认为 false

也可以按照 (this: Stencil, model: Model, group?: Group | null) => any 签名进行自定义布局。基本上表格内的布局已够用。

Step 4 拖拽

当我们在模板节点上按下鼠标开始拖动时,就等同于使用该节点调用了 dnd.start(node, e) 方法来触发拖拽,更多定制选项请参考上一节# react+antvX6 制作可编辑图表2——Dnd

image.png