mxStencil是什么
mxStencil是mxGraph提供的用于描述一类图形的xml,有什么用处呢?简单来说,就是给我们生成自定义图形提供了另外一种渠道。现在我们知道生成自定义图形有两种方式,一种是通过编码,还有一种就是mxStencil,两种方式各有优缺点,分情况使用。
mxStencil的定义规则
光知道mxStencil是什么还不行,毕竟光知道是什么写不出来也不行,接下来就详细说说,stencil的定义规则。
下图是我根据官方mxStencil的描述画出的表格,描述了stencil的标签的嵌套关系(由于官网的描述全是英文的,而我英语又是渣,所以有错误之处还望指出)。
通过上图,我们开始一个标签一个标签的分析。
- 我们可以看到最外层是shapes标签(但在官方的描述中,最外层是shape标签,在实际测试中使用shapes标签做为最外层标签是可以的),代表一组自定义形状的集合。
- 第二层是shape标签,用于实际定义一个形状。
shapes和shape标签属性 | |||
属性名 | 是否必须 | 说明 | 类型 |
name | required | 自定义图形的ID。 | String |
w | optional | 定义了图形操作的坐标系统的宽度。 | Number,默认值为100 |
h | optional | 定义了图形操作的坐标系统的高度。 | Number,默认值为100 |
aspect | optional | 缩放时是否保持宽高比。 | String,默认值为"variable"代表不需要保持宽高比,"fix"反之。 |
strokewidth | optional | 线条宽度。 | Number或者"inherit",默认值为1。"inherit"表示线条宽度仅在缩放时更改,而不是在调整大小时更改。如果使用数值,则在缩放和调整大小时都会改变线条宽度。 |
- connections标签,是一组连接点的集合。
- constraint标签,定义某个具体的连接点。
constraint标签属性 | |||
属性名 | 是否必须 | 说明 | 类型 |
perimeter | required | 连接点是否必须位于边界。 | Number,1或者0, 0代表由x,y指定连接点。1代表连接点的位置从形状的中心发出一条射线,经过x,y与图形边界的交点。 |
x,y | optional | 定义了连接点的位置。 | Number,x和y是固定点相对于图形边界的位置。perimeter为1,则会自动调整它们。例如,(0,0)是左上角,(0.5,0.5)是中心,(1,0.5)是右边界的中心等。若连接点在图形外值可以小于0或大于1。 |
name | optional | 连接点名称 | String,这个连接点唯一的ID。 |
- foreground标签,定义了图形的前景。
- background标签,定义了图形的背景。需要注意的是在background标签中,只可以包含rect,roundrect,path和ellipse标签。图形绘制分为前景和背景两个元素是为了定义应用于形状的任何阴影源自哪个部分(背景)。这意味着背景是形状外部的线描迹,但并非总是如此。
- text标签,用于定义一段文字,一般用于foreground标签中。
text标签属性 | |||
属性名 | 是否必须 | 说明 | 类型 |
x,y | required | 文字的起始位置 | Number |
str | required | 显示的字符串 | String |
align | optional | 文字的水平对齐方向 | String,"left", "center"或者"right",默认值是"left" |
localized | optional | 没理解... | |
vertical | optional | 文字方向 | Number,1或者0,若为1代表文字旋转90°,默认为0。 |
rotation | optional | 旋转 | Number,0到360,代表文件的旋转度数,默认为0。 |
align-shape | optional | 没理解... |
- rect标签,用于定义一个矩形,需要x,y,h和w四个属性,分别代表起始坐标和长宽。一般用于background标签中。
- roundrect标签,用于定义一个圆角矩形,需要x,y,h和w四个属性,分别代表起始坐标和长宽,还可以使用arcsize属性设置圆角的度数。一般用于background标签中。
- ellipse标签,需要x,y,h和w四个属性,分别代表起始坐标和长宽。用于定义一个圆形,一般用于background标签中。
- path标签,用于定义一段路径,一般用于background标签中,包含了move,line,quard,curve,arc和close标签。
- move标签,把路径移动到的指定点,不创建线条,需要x和y两个属性值,用于定义需要移动到的点,注意此处的x,y是相对于shape或者shapes标签上定义的w和h的。
- line标签,添加一个新点,然后在创建从该点到最后指定点的线条,需要x和y两个属性值。
- quad标签,创二次贝塞尔曲线,需要(x1,y1)和(x2,y2)四个属性值。
- curve标签,创建三次贝塞尔曲线,需要(x1,y1),(x2,y2)和(x3,y3)六个属性值。
- arc标签,创建弧线路径,详细可见MDN上关于SVG中关于弧线的描述,弧线的概念有些难以理解,在此简单说明:在调用arc标签之前,需要先调用move标签,确定弧线的起始位置。设置弧线的x和y属性,确定弧线的终点位置。接下来到重点了,连接弧线的起始位置和终点位置,可以得到一条线段,接下来做这条线段的中垂线,我们的圆心将出现在这条中垂线上。根据弧线的rx和ry属性我们可以在中垂线上找到两个圆心(或者一个圆心),两个圆心代表两个圆,代表有四条弧线可以供我们选择,接下来,我们就可以使用弧线的large-arc-flag属性确定是选择大弧还是小弧,再使用sweep-flag属性确定是选择从起始位置顺时针画的弧线还是从起始位置逆时针画的弧线。如果想让弧线旋转可以使用弧线的x-axis-rotation属性。
arc标签属性 | |||
属性名 | 是否必须 | 说明 | 类型 |
x,y | required | 弧线的终点 | Number |
rx,ry | required | x轴半径和y轴半径 | Number |
x-axis-rotation | required | x轴旋转角度 | Number,0或者1 |
large-arc-flag | required | 角度大小 | Number,0或者1 |
sweep-flag | required | 弧线方向 | Number,0或者1 |
- close标签,创建从当前点回到起始点的路径。
除了以上的标签外,mxStencil还提供了一套样式属性:
样式属性 | |
属性名 | 说明 |
strokecolor | 线段的颜色 |
fillcolor | 填充的颜色 |
fontcolor | 字体颜色 |
alpha | 透明度,取值范围为0到1 |
strokewidth | 线段的宽度 |
dashed | 是否启用虚线 |
linejoin | 决定了图形中两线段连接处所显示的样子。它可以是这三种之一:round, bevel 和 miter。默认是 miter。 |
linecap | 决定了线段端点显示的样子。它可以为下面的三种的其中之一:butt,round 和 square。默认是 butt。 |
miterlimit | 用来设定外延交点与连接点的最大距离,如果交点距离大于此值,连接效果会变成了 bevel。(没用过...) |
fontsize | 文字大小 |
fontstyle | 粗体(1),斜体(2)和下划线(4)的ORed位模式,即粗体下划线是“5”。 |
fontfamily | 字体 |
以上提及的所有颜色都采用以哈希为前缀的十六进制颜色代码(#78F7FE)
实际使用
光说不练假把式,自己动手写一个才是真的掌握了,先看下图:
我们需要使用mxStencil定义出一个这样的图形。
- 首先我们从xml的最外层shape标签开始,我们定义此图形的名称为test,宽为90,高度为40,缩放时不需要保持宽高比且线条宽度仅在缩放时更改。
<shape name="test" w="90" h="40" aspect="variable" strokewidth="inherit">
</shape>
- 接下来我们定义图形的连接点。需要注意的是连接点的坐标是0-1表示的,和其他的不同。
<shape w="90" h="40" aspect="variable" strokewidth="inherit">
<connections>
<constraint x="0" y="0.5" perimeter="0" />
<constraint x="1" y="0.5" perimeter="0" />
</connections>
</shape>
- 然后我们画出图形的背景部分,两个圆和两条线。
<shape w="90" h="40" aspect="variable" strokewidth="inherit">
<connections>
<constraint x="0" y="0.5" perimeter="0" />
<constraint x="1" y="0.5" perimeter="0" />
</connections>
<background>
<ellipse x="15" y="0" w="40" h="40" />
<stroke />
<ellipse x="35" y="0" w="40" h="40" />
<stroke />
<path>
<move x="75" y="20" />
<line x="85" y="20" />
</path>
<stroke />
<path>
<move x="5" y="20" />
<line x="15" y="20" />
</path>
<stroke />
</background>
</shape>
- 最后我们定义图形的前景部分,也就是文字部分。
<shape w="90" h="40" aspect="variable" strokewidth="inherit">
<connections>
<constraint x="0" y="0.5" perimeter="0" />
<constraint x="1" y="0.5" perimeter="0" />
</connections>
<background>
<ellipse x="15" y="0" w="40" h="40" />
<stroke />
<ellipse x="35" y="0" w="40" h="40" />
<stroke />
<path>
<move x="75" y="20" />
<line x="85" y="20" />
</path>
<stroke />
<path>
<move x="5" y="20" />
<line x="15" y="20" />
</path>
<stroke />
</background>
<foreground>
<text str="#1" x="15" y="15" align="left" valign="middle" vertical="0" rotation="0" localized="0" align-shape="0" />
<text str="#2" x="60" y="15" align="left" valign="middle" vertical="0" rotation="0" localized="0" align-shape="0" />
<text str="Y" x="25" y="25" align="left" valign="middle" vertical="0" rotation="0" localized="0" align-shape="0" />
<text str="Y" x="55" y="25" align="left" valign="middle" vertical="0" rotation="0" localized="0" align-shape="0" />
</foreground>
</shape>
大功告成我们看看效果。可以看到还是有改善空间的,比如连接点的位置还需要继续调整。
你可能会问是如何确定各个路径的坐标的,我想说,我有写轮眼。