Markers
撰写时间:2026-03-17
修订时间:2026-03-19
概述
可以先绘制一个图形,然后将该图形动态地添附到path, line, polyline及polygon等各种图形中。这种被添附的图形就称为marker,在SVG中使用marker标记。最常见的应用场合是为图形绘制箭头。
应用 marker 的3个步骤
因需要绘制两个图形,且marker的视口与现有图形的视口往往不一样,因此,可分三个步骤来实现。下面取为一条线段的末端绘制箭头为例说明。
第一步,先在一个较小的视口内绘制箭头。
这一步可让我们清晰地看到marker的原始形状。
第二步,将其定义为一个marker。
这一步,svg的viewBox及marker的viewBox分别引用了不同的视口坐标系。
refX及refY用以指定两个图形的连接点。这里的连接点取自第一步图形中的最后一个顶点。
将orient属性值设置为auto,则箭头的朝向会根据线段的朝向自动旋转。
运行后不会看到任何图形,这是因为在defs中所定义的元素不会被自动渲染。
第三步,引用marker。
marker-end属性值的含义是,在path元素的末尾添附所指定的marker。个人认为,这个属性名不够精准,若改为end-marker
似乎更容易理解。
同理,使用marker-start在线段始端添附marker,使用marker-mid在线段中间添附marker。
引用时指定不同的填充颜色
第一种方法是在定义marker时,将其fill属性值设置为SVG V2.0规范中的context-stroke,则marker的fill属性值取自引用主体的stroke属性值。
Chrome, Firefox, Edge及Opera均无问题。但Safari当前与IE一样糟糕,均不支持context-stroke属性值。
第二种方法是使用CSS变量,分别定义两种颜色的箭头。
通过将marker及引用主体共享同一CSS变量,可确保两者颜色完全一致。但遗憾的是,这种方法将不可避免地产生较多冗余代码。
第三种方法是通过JavaScript来动态创建。
对于每个绘制箭头的path,取出其stroke颜色值,并赋值于一个动态创建的marker的fill属性,最后将path的marker-end属性值指向此动态创建的marker。
最后两行专为Safari服务,因为其应用了缓存机制,当我们使用JavaScript动态设置后,需利用这两行代码让其重绘svg,否则箭头的颜色值默认为黑色。Chrome则不需要这两行代码也可正常工作。
定制 marker 尺寸
可通过marker的markerUnits, markerWidth及markerHeight这3个属性来定制marker的尺寸。
默认设置
默认情况下,marker的大小将取决于引用主体的stroke-width属性值。
引用主体path的stroke-width的值是20,且marker的markerHeight属性值为1,则被添附的marker的最终高度值为20。其计算公式为:
marker的markerWidth的值是5,为何不参与计算最终的尺寸?
marker在定义时通过将viewBox属性值设置为0 0 10 10
,从而定义了固定的宽高比(这里为1 / 1),在被添附时,需按比例缩放,从而保证marker随引用主体的尺寸改变而改变,从而在视觉上保持一致。
而为达到按比例缩放的要求,在我们同时指定markerWidth及markerHeight的值时,将取这两者的最小值参与缩放计算。因此上面的公式可改为:
为简化问题,重回到原来的公式:
从公式可看出,这里是倍数与单位相乘的关系。markerHeight充当倍数。如何确定单位?正如其名,markerUnits用于指定如何确定单位值。其值为stroke-width,则取引用主体的stroke-width值作为这里的单位值。
由于markers通常用于添附在一条线段或弧线上,因此这种机制只要我们指定了线段或弧线的宽度,则被添附的marker将自动进行较为完美的缩放。
自由指定
语法及其含义
将marker的markerUnits属性值设置为userSpaceOnUse,则marker的大小不再由引用主体的stroke-width属性值确定,而是在定义marker时通过指定其markerWidth及markerHeight属性值来确定其大小。
由于需要保持marker在声明时的比例,因此,当我们同时指定markerWidth及markerHeight属性值时,引擎将按声明时的比例缩放至这两个值的最小值。这两个值默认值均为3。分别修改markerWidth及markerHeight属性值,观察不同的运行结果,以验证我们的认知。
因此,当markerUnits的值为userSpaceOnUse时,意为marker的大小将按引用坐标系中的单位来确定,其宽度及高度值则分别由markerWidth及markerHeight属性来提供。
自由变化的线宽
由于marker的大小不再受引用主体的stroke-width约束,因此我们可以独立调节两者的大小。
修改引用主体的stroke-width属性值,以取得最佳适配效果。
CSS属性: marker
可以为引用主体使用CSS的marker属性来添附各种markers。
这种方式,不仅可以在引用主体的首尾处、还可以在路径的拐弯处 (path segments) 添附各个markers。
无需任何JavaScript代码,就可得到这种灵便而强大的特性,这就是SVG的威力与魅力所在。
参考资源
- SVG 1: Markers
- SVG 2: Specifying paint
