Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Draw text in SVG but remove background

Tags:

svg

I'm working with an SVG element that should look something like 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)

A border with rounded corners in the middle of a page, but where the the border is removed where header/footer is to be inserted. User-specified text is to be inserted into header, footer and into the frame itself. The rectangle is painted on top of another background (a picture, another rectangle with a color, etc.). I need to find a way to keep the original background, paint only parts of the border and place the text on top of the original background.

I have come up with this solution:

<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>

My problem now is that the last two rects in the mask (rectangles where not to draw the border) must have a static width. If the user changes the text width, the user also needs to calculate a new with of the text and update these two rectangles.

Is there a way to mask out a block the exact same width as the text itself and skip the rectangles in the mask. Or is this the only way of creating such a mask? If anybody "out there" has a better and more intuitive way of achieving this layout, I'd be more than interested in hearing from you.

Thanks for your help.

like image 909
Iznogood Avatar asked Sep 04 '12 09:09

Iznogood


People also ask

Can you insert text in SVG?

The SVG <text> element draws a graphics element consisting of text. It's possible to apply a gradient, pattern, clipping path, mask, or filter to <text> , like any other SVG graphics element. If text is included in SVG not inside of a <text> element, it is not rendered.

Why does my SVG have a background color?

The background color of the SVG is borrowed from the component it is sitting in. (kinda like svg borrows the page colour, and the default page colour is white).


1 Answers

"Removing the background" of svg text without scripting can be done using svg filters.

For example:

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

Which can be used by the text like this:

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

This will adapt to the string width automatically. If you need some padding you can tweak the x,y,width,height attributes on the filter element.

Hmm, thinking of this again, this might not be what you wanted exactly. But it's possible to adapt the above. Here's your file with this solution:

<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>
like image 150
Erik Dahlström Avatar answered Sep 23 '22 21:09

Erik Dahlström