在SVG中绘制文本但去除背景。

8
我正在处理一个SVG元素,它应该看起来像这样:(对不起,我必须把它发布为链接而不是图片,但作为新用户,我没有权限发布图片) 在页面中间有一个带圆角的边框,但在插入页眉/页脚的地方移除边框。用户指定的文本将被插入到页眉、页脚和框架中。矩形被涂在另一个背景(图片、另一个带颜色的矩形等)之上。我需要找到一种方法来“保留”原始背景,仅绘制部分边框并将文本放置在原始背景之上。
我想出了以下解决方案:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="0 0 620 1100" preserveAspectRatio="xMidYMid meet">
    <defs>
        <!--Define some texts-->
        <text id="text1" x="90" y="100" style="text-anchor:start;font-size:30px;">THIS IS MY HEADER</text>
        <text id="text2" x="525" y="1010" style="text-anchor:end;font-size:30px;">MY TEXT HERE</text>

        <mask id="Mask1">
            <!--draw the entire screen-->
            <rect x="0" y="0" width="620" height="1100" style="fill:white;" />
            <!--Mask out the two rectangles where text is to be placed-->
            <rect x="300" y="980" width="350" height="50" style="fill:black;" />
            <rect x="90" y="90" width="350" height="40" style="fill:black;" />
        </mask>
    </defs>

    <!--The original background (here a rect with a fill color, but could also be an image)-->      
    <rect x="0" y="0" width="620" height="1100" style="fill:#f0ffb6"/>
    <!--Draw the rectangle but applying the mask-->
    <rect x="100" y="100" rx="20" ry="20" width="420" height="900" mask="url(#Mask1)" style="fill:none;stroke:green;stroke-width:5"/>

    <!--Draw the text-->                
    <use xlink:href="#text1" fill="black" stroke="black" stroke-width="1" />
    <use xlink:href="#text2" fill="black" stroke="black" stroke-width="1" />

    <text x="200" y="200">This text goes into the border</text>
</svg>

我的问题是遮罩中最后两个矩形(不画边框的矩形)必须有固定宽度。如果用户改变了文本的宽度,用户还需要计算文本的新宽度并更新这两个矩形。

是否有一种方法可以屏蔽与文本本身完全相同宽度的区块,并跳过遮罩中的矩形?或者这是创建这样一个遮罩的唯一方法?如果有人有更好和更直观的方法来实现此布局,我将非常感兴趣听取您的意见。

谢谢您的帮助。


没有 JavaScript 的话,这会比第一眼看起来的要更加复杂。这里提供一个可能的解决方法:https://dev59.com/Isgoz4gBFxS5KdRjbnWN#8680391 - methodofaction
我担心如果不使用脚本,这将会很困难。有没有其他方法可以实现类似的效果而不使用遮罩?我一直在尝试使用stroke="green"的textPath,并尝试调整描边的起点,使绿色线条在文本之后开始。 - Iznogood
2个回答

22

可以使用SVG滤镜来“移除”没有脚本的SVG文本的背景。

例如:

<filter x="0" y="0" width="1" height="1" id="removebackground">
   <feFlood flood-color="blue"/>
   <feComposite in="SourceGraphic"/>
</filter>

可以像这样使用:

<use xlink:href="#text1" fill="black" filter="url(#removebackground)"/>

这将自动适应字符串的宽度。如果需要一些填充,您可以调整过滤器元素上的x、y、width和height属性。

嗯,再思考一下,这可能不是您想要的确切解决方案。但是可以根据上述方法进行调整。这是使用此解决方案的文件:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="0 0 620 1100" preserveAspectRatio="xMidYMid meet">
    <defs>
        <!--Define some texts-->
        <text id="text1" x="90" y="100" style="text-anchor:start;font-size:30px;">THIS IS MY HEADER</text>
        <text id="text2" x="525" y="1010" style="text-anchor:end;font-size:30px;">MY TEXT HERE</text>
        <filter x="0" y="0" width="1" height="1" id="removebackground">
            <feFlood flood-color="black"/>
        </filter>

        <mask id="Mask1">
            <!--draw the entire screen-->
            <rect x="0" y="0" width="620" height="1100" style="fill:white;" />
            <!--Mask out the two rectangles where text is to be placed-->
            <use xlink:href="#text1" filter="url(#removebackground)"/>
            <use xlink:href="#text2" filter="url(#removebackground)"/>
        </mask>
    </defs>

    <!--The original background (here a rect with a fill color, but could also be an image)-->      
    <rect x="0" y="0" width="620" height="1100" style="fill:#f0ffb6"/>
    <!--Draw the rectangle but applying the mask-->
    <rect x="100" y="100" rx="20" ry="20" width="420" height="900" mask="url(#Mask1)" style="fill:none;stroke:green;stroke-width:5"/>

    <!--Draw the text-->                
    <use xlink:href="#text1" fill="black" stroke="black" stroke-width="1" />
    <use xlink:href="#text2" fill="black" stroke="black" stroke-width="1" />

    <text x="200" y="200">This text goes into the border</text>
</svg>

1
注意:它的效果不如预期,会使文本看起来有些“破碎”或“薄弱”。 - Erti-Chris Eelmaa

5

我认为影响这一点的简单方法是使用用户的文本作为亮度蒙版,并设置大笔画宽度和黑色笔画。接下来,将文本正常地放置在被蒙版遮挡的边框上方。


我想补充一下,边框掩码应该由一个页面大小的白色矩形组成,超粗的描边文本为黑色,在边框上留下与文本大小相同的间隙,而不需要编写脚本。 - Jack
这是一个非常聪明简便的实现我所需效果的方法。我从未想过。虽然我认为Erik Dahlström的解决方案是“正确”做法,但由于事实证明,像Adobe和iBooks这样的电子书呈现器不能正确使用滤镜,所以你的解决方案最有可能是我会使用的解决方案。像往常一样,我们必须要放弃正确去做一些可行的hack。编辑:由于我没有足够的声望来投票“此答案有用”,可以有人帮我投一下吗? - Iznogood
8
听起来很聪明,你能为我们提供一个具体的例子吗? - Alastair Maw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接