为什么我的SVG路径在Chrome,Edge和Firefox中被意外剪辑?

时间:2017-11-16 17:27:47

标签: svg

考虑以下SVG图像代码:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000">
    <title>Clipped Path Problem Demo</title>
    <g id="group:image">
        <defs>
            <mask id="mask">
                <rect id="rectangle:inset" x="250" y="134" width="500" height="732" fill="white"/>
            </mask>
        </defs>
        <g id="group:curves" mask="url('#mask')">
            <!-- <rect id="rectangle:filler.shape" width="1" height="1" fill="transparent"/> -->
            <path id="path:curves" d="
                M 441 327
                c -85 88 -85 175 -85 175
                c 0 88 85 175 85 175
                s 90 103 90 103
                c 85 88 85 175 85 175" fill="transparent" stroke="black" stroke-width="73"/>
        </g>
    </g>
    <g id="group:guides">
        <rect id="rectangle:guide.area:inset" x="250" y="134" width="500" height="732" fill="transparent" stroke="black" stroke-dasharray="20 10" stroke-width="1"/>
    </g>
</svg>

(CodePen:https://codepen.io/patrickdark/full/zPEVVg/。(我在笔中添加了height="500px"属性,使其更有可能适合屏幕。))

弯曲路径的左侧侧被剪切为垂直线,即使蒙版的大小远远超过了包含该部分图像所需的大小。

如果我将具有非零维度的任何大小的形状插入到蒙版的g元素中 - 例如XML注释中的1×1透明矩形 - 剪裁的边缘将被神奇地取消剪切。

我认为这是一个错误,除了它发生在Chrome(62),Edge(41)和Firefox Developer Edition(58 Beta 4)中。我想知道的是为什么这种看似荒谬的裁剪正在发生。

(注意:曲线路径底部的剪辑是有意的。)

1 个答案:

答案 0 :(得分:2)

由于蒙版适用于颜色和Alpha通道值(可能是代价高昂的操作),因此它不会拉伸到无穷大,但默认情况下会在蒙版元素的对象边界框处剪切渲染在每个方向加10%(由边界框单元中的属性x, y, width, height定义)。

对象边界框虽然定义为不包括笔划宽度。您超出了这些限制,需要至少对面具的xwidth属性进行调整。

由于这似乎不直观,因此应用掩码的一般算法如下:

  1. 确定应用蒙版的区域。这始终是x, y, width, height元素的<mask>属性给出的矩形。如果默认情况下maskUnits属性为objectBoundingBox,则坐标由应用蒙版的元素的object bounding box确定。掩码的内容被考虑在内。该坐标系中的0和1是被遮罩元素及其所有后代的连接边界框的最小值和最大值。
  2. 将mask元素的内容与应用它的元素叠加在一起。默认情况下,用于放置这些元素的坐标系统为maskContentUnits="userSpaceOnUse",这意味着绘制蒙版元素的坐标系相同。
  3. 对于上面定义的区域内的每个点,将屏蔽内容的不透明度与屏蔽内容的亮度相乘,以计算屏蔽元素的最终不透明度。
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000">
        <title>Clipped Path Problem Resoved</title>
        <g id="group:image">
            <defs>
                <mask id="mask" x="-20%" width="140%">
                    <rect id="rectangle:inset" x="250" y="134" width="500" height="732" fill="white"/>
                </mask>
            </defs>
            <g id="group:curves"mask="url('#mask')">
                <!-- <rect id="rectangle:filler.shape" width="1" height="1" fill="transparent"/> -->
                <path id="path:curves" d="
                    M 441 327
                    c -85 88 -85 175 -85 175
                    c 0 88 85 175 85 175
                    s 90 103 90 103
                    c 85 88 85 175 85 175" fill="transparent" stroke="black" stroke-width="73"/>
            </g>
        </g>
        <g id="group:guides">
            <rect id="rectangle:guide.area:inset" x="250" y="134" width="500" height="732" fill="transparent" stroke="black" stroke-dasharray="20 10" stroke-width="1"/>
        </g>
    </svg>