svg mask和stroke冲突问题

目录

  • 先说结论
  • 各种样例
    • 首先是水平、垂直的线
    • 然后是斜线
    • 如果是图形加stroke呢
    • 用《g》标签包起来呢
  • 总结

先说结论

实际上svg里,mask对svg内元素起作用的并非元素本身,而是元素几何形状的外包矩形,特别是和stroke有冲突,会产生奇怪的显示效果

各种样例

首先是定义一个普通的svg,包含了渐变的mask

<html>
<body>
<svg width="1000" height="1000" >
    <defs>
		<linearGradient  id="border-with-four-corner-linearGradient1" x1="0%" y1="0%" x2="100%" y2="100%">
			<stop offset="0" stop-color="white" stop-opacity="0">stop>
			<stop offset="0.5" stop-color="white" stop-opacity="1">stop>
			<stop offset="1" stop-color="white" stop-opacity="0">stop>
		linearGradient>
		<mask  id="border-with-four-corner-mask1">
			<rect  x="0" y="0" width="1000" height="1000" fill="url(#border-with-four-corner-linearGradient1)">rect>
		mask>
    defs>
    这里放后面的各种path
  svg>
  body>
 html>

首先是水平、垂直的线

代码放到上面代码中”这里放后面的各种path“的地方

<path d="M 100 10 l 200 0" stroke="green" stroke-width="20" fill="none" mask="url(#border-with-four-corner-mask1)" />

理论上来说会获取一条渐变的水平线段,宽度20,但是显示是空白
同样的

<path d="M 100 10 l 0 200" stroke="green" stroke-width="20" fill="none" mask="url(#border-with-four-corner-mask1)" />

理论上来说会获取一条渐变的垂直线段,宽度20,但是显示是空白

由上面可以得到,stroke并不会改变mask作用的几何图形的范围,上述的水平或者垂直线的几何图形范围(面积)还是0,因此显示的结果自然是空白的
多点、加z或者fill也一样的

<path d="M 100 10 l 200 0 l 100 0 z" stroke="green" stroke-width="20" fill="red" mask="url(#border-with-four-corner-mask1)" />

然后是斜线

<path d="M 100 10 l 200 1" stroke="green" stroke-width="20" fill="none" mask="url(#border-with-four-corner-mask1)" />

出现了渐变的线了,因为这条线的几何外包矩形不再是面积0了。但是发现线宽度不是20,而是很细,大概只有1

<path d="M 100 10 l 200 5" stroke="green" stroke-width="20" fill="none" mask="url(#border-with-four-corner-mask1)" />

也出现了渐变的线了,因为这条线的几何外包矩形不再是面积0了。但是发现线宽度不是20,而是很细,大概只有5
因此可以得出结论包含stroke的线,在mask下,最终的显示宽度受限制于最小的宽度或者高度

如果是图形加stroke呢

<rect x="100" y="200" width="300" height="50" fill="red" stroke="green" stroke-width="30"  mask="url(#border-with-four-corner-mask1)"/>
		<rect x="100" y="400" width="300" height="50" fill="red" stroke="green" stroke-width="30"/>

两个300*50的长方形,一个加了mask,一个没有加,都是stroke绿色宽30
svg mask和stroke冲突问题_第1张图片
结果是这样的,加了mask的被拉扁了,没错stroke被拉扁了,几何图形范围没有变化,但是stroke被拉扁了

那改变宽度和高度,改为150*150的正方形

<rect x="100" y="200" width="150" height="150" fill="red" stroke="green" stroke-width="30"  mask="url(#border-with-four-corner-mask1)"/>
		<rect x="100" y="400" width="150" height="150" fill="red" stroke="green" stroke-width="30"/>

svg mask和stroke冲突问题_第2张图片
渲染是对的,宽度没错了。

用《g》标签包起来呢

将水平和垂直的线,利用group包起来,对group加mask

<g  mask="url(#border-with-four-corner-mask1)">
		<path d="M 100 10 l 200 0" stroke="green" stroke-width="20" fill="none" />
		<path d="M 100 10 l 0 500" stroke="green" stroke-width="20" fill="none" />
	g>

svg mask和stroke冲突问题_第3张图片

显然,结果是对的,因为这个group的几何外包矩形是200*500(线的长度不同),显示正常,而且不会像矩形那样stroke被拉扁
这样也不会拉扁矩形的stroke

	<g  mask="url(#border-with-four-corner-mask1)">
		<path d="M 100 10 l 200 0" stroke="green" stroke-width="20" fill="none" />
		<rect x="100" y="200" width="300" height="50" fill="red" stroke="green" stroke-width="30"/>
	g>

或者这样两个矩形也不会拉扁

<g  mask="url(#border-with-four-corner-mask1)">
		<rect x="100" y="100" width="500" height="50" fill="red" stroke="green" stroke-width="30"/>
		<rect x="100" y="200" width="500" height="50" fill="red" stroke="green" stroke-width="30"/>
	g>

但单独一个矩形放再group里还是会拉扁的

	<g  mask="url(#border-with-four-corner-mask1)">
		<rect x="100" y="200" width="300" height="50" fill="red" stroke="green" stroke-width="30"/>
	g>

总结

再说一遍结论
实际上svg里,mask对svg内元素起作用的并非元素本身,而是元素几何形状的外包矩形,特别是和stroke有冲突,会产生奇怪的显示效果
对我们的启示,尽可能不要对包含stroke的元素进行mask操作,如果必须的话,那么用group标签包起来,确保group标签内存在至少两个几何图形

你可能感兴趣的:(svg,前端)