1. 前言
使用X6最常用的场景,或者说最基础的场景,就是官网给出的第一个demo案例——流程图。 X6官网图表示例
左侧的这个侧边栏提供基础的UI组件,通过拖拽这些组件,可以在右侧的画布上进行绘制。该功能是通过插件
@antv/x6-plugin-stencil来实现的。
官网上提供了完整的案例代码。这里,改写下用cdn方式导入资源包,将ts改为js写法。最终要实现的效果如下图所示:
2.熟悉X6插件之Stencil
2.1 认识Stencil
从上图可以看到,在系统设计图的group下,有6个节点,该节点是携带了label文字和图标两个元素。在拓展左侧工具面板的功能之前,先要了解下x6-plugin-stencil的基础功能。已经使用过该插件或者了解过该功能的可以跳转到添加svg图标。
2.2 创建分组
左侧面板中基本流程图和系统流程图通过分组区分开。如下代码所示:
const stencil = new Stencil({
title: '流程图',
target: graph,
stencilGraphWidth: 200,
stencilGraphHeight: 180,
collapsable: true,
groups: [
{
title: '基础流程图',
name: 'group1',
},
{
title: '系统设计图',
name: 'group2',
graphHeight: 250,
layoutOptions: {
rowHeight: 70,
},
},
],
layoutOptions: {
columns: 2,
columnWidth: 80,
rowHeight: 55,
},
})
其中有几个参数的设置注意下:
collapsable: 是否显示全局折叠/展开按钮,默认为false,这里设置为true,显示折叠按钮。(注意:这里并不是默认折叠或展开的开关,而是是否显示按钮的开关。)groups:分组信息,数组类型,在分组下面定义单个分组的信息,包括展示的标题title,指定的分组名称name,如果分组标题title缺少的时候,会默认用name作为分组标题。collapsed:初始状态是否为折叠状态,在group内部使用,试了在外部使用没效果。为true表示折叠,false为展开。默认值是false,即展开。columns:网格布局的列数,默认为2。行数根据节点数自动计算。columnWidth:列宽。rowHeight:行高。
分组内的一些配置和外层的配置有重合,比如 layoutOptions,分组内的配置优先级比较高。
2.3 注册节点
调用 Graph 的静态方法 registerNode 来注册节点,注册以后就可以像使用内置节点那样来使用节点。这个方法在1.34.6的官网文档中有说明,在2.x文档中搜索不到该方法,但是使用2.x版本的X6,也是可以调用registerNode方法的。1.x版本的自定义节点-官网(疑惑!!为啥最新的文档上就找不到了呢?)
Graph.registerNode(
'custom-image',
{
inherit: 'rect',
width: 52,
height: 52,
markup: [
{
tagName: 'rect',
selector: 'body',
},
{
tagName: 'image',
},
{
tagName: 'text',
selector: 'label',
},
],
attrs: {
body: {
stroke: '#5F95FF',
fill: '#5F95FF',
},
image: {
width: 26,
height: 26,
refX: 13,
refY: 16,
},
label: {
refX: 3,
refY: 2,
textAnchor: 'left',
textVerticalAnchor: 'top',
fontSize: 12,
fill: '#fff',
},
},
ports: { ...ports },
},
true,
)
这里自定义了一个名为 'custom-image' 的节点。里面的参数的含义就不一一写出来了,字面意就很明显。
2.4 创建节点
注册以后,我们可以像下面这样来创建。
graph.createNode({
shape: 'custom-image',//已经注册好的自定义节点
label: "Client",
attrs: {
image: {
'xlink:href': 'https://gw.alipayobjects.com/zos/bmw-prod/687b6cb9-4b97-42a6-96d0-34b3099133ac.svg',
},
body: {
strokeWidth: 1,
stroke: '#5F95FF',
fill: '#5F95FF',
},
},
}),
案例中通过SVG图标链接的方式来展示。存在多个svg的时候,将label和image提取到数组中。
const imageShapes = [
{
label: 'Client',
image:
'https://gw.alipayobjects.com/zos/bmw-prod/687b6cb9-4b97-42a6-96d0-34b3099133ac.svg',
},
{
label: 'Http',
image:
'https://gw.alipayobjects.com/zos/bmw-prod/dc1ced06-417d-466f-927b-b4a4d3265791.svg',
},
{
label: 'Api',
image:
'https://gw.alipayobjects.com/zos/bmw-prod/c55d7ae1-8d20-4585-bd8f-ca23653a4489.svg',
},
{
label: 'Sql',
image:
'https://gw.alipayobjects.com/zos/bmw-prod/6eb71764-18ed-4149-b868-53ad1542c405.svg',
},
{
label: 'Clound',
image:
'https://gw.alipayobjects.com/zos/bmw-prod/c36fe7cb-dc24-4854-aeb5-88d8dc36d52e.svg',
},
{
label: 'Mq',
image:
'https://gw.alipayobjects.com/zos/bmw-prod/2010ac9f-40e7-49d4-8c4a-4fcf2f83033b.svg',
},
]
const imageNodes = imageShapes.map((item) =>
graph.createNode({
shape: 'custom-image',
label: item.label,
attrs: {
image: {
'xlink:href': item.image,
},
body: {
strokeWidth: 1,
stroke: '#5F95FF',
fill: '#5F95FF',
},
},
}),
)
2.5 加载节点
最后,将节点进行加载,绑定到对应的分组上去。
stencil.load(imageNodes,'group2')
3. 添加svg图标
3.1 加载本地svg格式文件
是否可以基于这个改写下,去掉label文字描述,去掉背景元素,更改图标的颜色呢?
虽然通过链接的方式可以加载svg图标,达到目的效果,但是我们在查找图标的时候,有时候看到的并不是在线的无鉴权的链接。这里,我们访问【ant design的图标库】,打开控制台,定位到指定的图标。
可以看到这是一段svg的路径。很多的加载svg图标的都是svg直接加载。
如果能将复制下来的svg的路径直接使用,就可太方便了,很多的icon都可以通过控制台拿到。
3.2 将svg的数据转为base64
参照demo中上述的注册节点、创建节点和使用节点的方式,来新建一个group,注册一个名为icon-svg的节点。创建如下方法
function svgToDataURL(svgPath) {
const svgCode = `
<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" >
<path d="${svgPath}"></path>
</svg>
`;
const encoded = window.btoa(svgCode);
return `data:image/svg+xml;base64,${encoded}`;
}
划重点了,将svg的格式图片转为base64,进行加载,这个即为本次文章的中心思想。但是这样直接转过来之后,不能更改颜色了,所以在svg这步,就要将颜色渲染进去。
function svgToDataURL(svgPath,fillColor = "#f00") {
const svgCode = `
<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" style="fill:${fillColor}">
<path d="${svgPath}"></path>
</svg>
`;
const encoded = window.btoa(svgCode);
return `data:image/svg+xml;base64,${encoded}`;
}
3.3 复制svg路径的时候注意事项
存在很多的svg图标,不止一个path路径,会存在多个。如下:
这里可以进一步改写下上述的方式。
方式一:<path d="${svgPath}"></path>改为如上图加载的,svg标签下的字内容全部复制。
方式二:将两个路径合并成一个。合并的时候需注意,两段路径之间并不需要标点符号进行区分,就直接拼接在一起就可以了。
八青妹这里采用的方式二。完整代码:
4. 总结
icon图标在流程图中是为了让流程图的显示更加丰满一些。既然官网的案例给了svg链接加载的方式,那么肯定也是支持base64图片加载的,将svg的格式文件转为base64,仿照demo完成图标库的基本搭建。最后就是需要什么图标,在线查找最后复制粘贴进项目代码中就可以啦!