目录
- 先说结论
- 各种样例
- 首先是水平、垂直的线
- 然后是斜线
- 如果是图形加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
结果是这样的,加了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"/>
渲染是对的,宽度没错了。
用《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>
显然,结果是对的,因为这个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标签内存在至少两个几何图形