在 SVG 中绘制文本但删除背景

Posted

技术标签:

【中文标题】在 SVG 中绘制文本但删除背景【英文标题】:Draw text in SVG but remove background 【发布时间】:2012-08-28 22:18:15 【问题描述】:

我正在使用类似于 this: (sorry that I have to post this as a link instead of as a picture, but as a new user I didn't have permissions to post images) 的 SVG 元素

页面中间带有圆角的边框,但在要插入页眉/页脚的位置移除了边框。用户指定的文本将被插入页眉、页脚和框架本身。该矩形被绘制在另一个背景(图片、另一个带有颜色的矩形等)之上。我需要找到一种方法来保留原始背景,仅绘制部分边框并将文本放置在原始背景之上。

我想出了这个解决方案:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"   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"   style="fill:white;" />
            <!--Mask out the two rectangles where text is to be placed-->
            <rect x="300" y="980"   style="fill:black;" />
            <rect x="90" y="90"   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"   style="fill:#f0ffb6"/>
    <!--Draw the rectangle but applying the mask-->
    <rect x="100" y="100" rx="20" ry="20"   mask="url(#Mask1)" style="fill:none;stroke:green;stroke-width:5"/>

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

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

我现在的问题是掩码中的最后两个矩形(不是绘制边框的矩形)必须具有静态宽度。如果用户改变了文本宽度,用户还需要计算一个新的文本宽度并更新这两个矩形。

有没有办法屏蔽与 text 本身宽度完全相同的块并跳过掩码中的矩形。或者这是制造这种面具的唯一方法?如果“外面”的任何人有更好、更直观的方式来实现这种布局,我会非常有兴趣收到你的来信。

感谢您的帮助。

【问题讨论】:

如果没有 javascript,这比乍看之下要复杂得多。这是一个可能的解决方法***.com/a/8680391/524555 我担心如果不编写脚本会很困难。有没有其他方法可以在不使用口罩的情况下达到类似的效果?我一直在尝试使用带有 stroke="green" 的 textPath 的想法,并尝试调整笔触的开始,以便绿线在文本之后开始。 【参考方案1】:

可以使用 svg 过滤器来完成无需脚本的 svg 文本的“删除背景”。

例如:

<filter x="0" y="0"   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"   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"   id="removebackground">
            <feFlood flood-color="black"/>
        </filter>

        <mask id="Mask1">
            <!--draw the entire screen-->
            <rect x="0" y="0"   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"   style="fill:#f0ffb6"/>
    <!--Draw the rectangle but applying the mask-->
    <rect x="100" y="100" rx="20" ry="20"   mask="url(#Mask1)" style="fill:none;stroke:green;stroke-width:5"/>

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

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

【讨论】:

当心:它不能正常工作,它会使文本看起来有点“破碎”或“弱”。【参考方案2】:

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

【讨论】:

我可能会补充一点,边框蒙版应该由一个页面大小的白色矩形和黑色的超粗笔划文本组成,在没有脚本的情况下在边框中留下文本大小的间隙。 这是实现我想要的效果的一种非常简单的方法。我从来没想过这点。尽管我认为 Erik Dahlströms 解决方案是“正确”的解决方案,但您的解决方案很可能是我将使用的解决方案,因为事实证明,像 Adob​​e 和 iBooks 这样的 e-pub 渲染器无法使用过滤器正确运行。与往常一样,人们将不得不放弃正确的做法,并做一些可行的技巧。编辑:因为我没有足够的声誉来投票“这个答案很有用”,有人可以帮我做吗? 听起来很聪明;你有具体的例子吗?

以上是关于在 SVG 中绘制文本但删除背景的主要内容,如果未能解决你的问题,请参考以下文章

在 SVG 中绘制文本但删除背景

ImageBitmap from SVG - 一些字体大小的锯齿状文本

SVG raw 未在颤动中显示文本

如何使用javascript动态更改html中svg的文本内容

在 d3 arc javascript 中绘制文本

d3中的多行svg文本轴刻度