一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
项目需求: 最近有一个项目是电路的模拟实验平台,需求为需要有一个工作画布,和一个组件库,实现组件器械的可拖拽、可连接,实验状态可以控制,数据流向展示等功能。就像我们平时课上的虚拟仿真平台一样,又需要像流程图软件一样,可以托拽各种组件到画布中。最后我选择使用antv的X6来制作。
前清提要: 上一期我们讲了antv-X6中的拖拽组件Dnd,这一期我们讲一讲拖拽组件Stencil(详细内容可以参考官方文档)。
Stencil
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.title | string | 'Stencil' | |||||
| options.groups | Group[] | ✓️ | 分组信息。 | ||||
| options.search | Filter | false | 搜索选项。 | ||||
| options.placeholder | string | 'Search' | 搜索文本框的 placeholder 文本。 | ||||
| options.notFoundText | string | 'No matches found' | 未匹配到搜索结果时的提示文本。 | ||||
| options.collapsable | boolean | false | 是否显示全局折叠/展开按钮。 | ||||
| options.layout | (this: Stencil, model: Model, group?: Group | null) => any | 网格布局 | 模板画布中节点的布局方法。 | |||
| options.layoutOptions | any | 布局选项。 | |||||
| options.stencilGraphWidth | number | 200 | 模板画布宽度。 | ||||
| options.stencilGraphHeight | number | 800 | 模板画布高度。 | ||||
| options.stencilGraphPadding | number | 10 | 模板画布边距。 | ||||
| options.stencilGraphOptions | Graph.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 来对节点进行自动布局,默认使用网格布局方法来布局模板节点,支持的布局选项有:
| 选项 | 类型 | 默认值 | 说明 | ||
|---|---|---|---|---|---|
| columns | number | 2 | 网格布局的列数,默认为 2。行数根据节点数自动计算。 | ||
| columnWidth | number | 'auto' | 'compact' | 'auto' | 列宽。auto: 所有节点中最宽节点的宽度作为列宽,compact: 该列中最宽节点的宽度作为列宽。 |
| rowHeight | number | 'auto' | 'compact' | 'auto' | 行高。auto: 所有节点中最高节点的高度作为行高,compact: 该行中最高节点的高度作为行高。 |
| dx | number | 10 | 单元格在 X 轴的偏移量,默认为 10。 | ||
| dy | number | 10 | 单元格在 Y 轴的偏移量,默认为 10。 | ||
| marginX | number | 0 | 单元格在 X 轴的边距,默认为 0。 | ||
| marginY | number | 0 | 单元格在 Y 轴的边距,默认为 0。 | ||
| center | boolean | true | 节点是否与网格居中对齐,默认为 true。 | ||
| resizeToFit | boolean | false | 是否自动调整节点的大小来适应网格大小,默认为 false。 |
也可以按照 (this: Stencil, model: Model, group?: Group | null) => any 签名进行自定义布局。基本上表格内的布局已够用。
Step 4 拖拽
当我们在模板节点上按下鼠标开始拖动时,就等同于使用该节点调用了 dnd.start(node, e) 方法来触发拖拽,更多定制选项请参考上一节# react+antvX6 制作可编辑图表2——Dnd