How do I create SVG with transparent text? - svg

I'm trying to create a svg button with transparent text. It looks like there is no way to do it easily in React-native, so maybe I'll just create an svg, that will have transparent text. How do I do that?
I've tried to do it in Figma, but it looks like the only way to do it there is to put a specific image behind. Text can't be truly transparent, it can only mask a picture.

You can use an svg mask with a white rectangle and a black text. The shapes you have - like the rectangle with rounded corners in this example - will be painted only under the white parts of the mask. Since the text is black it will apear like a hole.
svg{border:solid; background:silver;}
<svg>
<mask id="m">
<rect x="10" y="10" width="280" height="130" fill="white" />
<text x="150" y="75" font-size="90" font-family="arial" dominant-baseline="middle" text-anchor="middle" fill="black">text</text>
</mask>
<rect x="10" y="10" width="280" height="130" rx="20" mask="url(#m)" />
</svg>

Related

SVG text slightly off center

I have some text on a blue rectangle, centered horizontally and vertically. It is nearly perfectly in the center, however it is slightly too high. How can I fix this so that it is perfectly centered?
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg">
<g>
<rect fill="#8080ff" height="400" width="400" y="0" x="0"/>
<text font-weight="bold" stroke="black" x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" font-family="Arial, sans-serif" font-size="24" stroke-width="0" fill="#000000">Go</text>
</g>
</svg>
Changing dominant-baseline: middle to dominant-baseline: central fixed the problem. I had to look this up but if I understand it correctly, central prioritises the ideographic baseline whereas middle prioritises the alphabetic baseline. The alphabetic baseline hugs the bottom of the text, whereas the ideographic baseline rests just below the text. This extra space also sits above the text (regardless of the baseline being used), so you have to use the ideographic baseline to accomodate for this extra space, to centre it perfectly.
I think that's how it works anyway. These are the links I used to figure it out, if you want to understand it more.
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/dominant-baseline
What is the difference between alphabetic and ideographic in Flutter's TextBaseline enum

Issue with z-order of elements in SVG being rendered incorrectly

I created an SVG image as defined by the code below. The issue I am having is that the SVG image is being rendered incorrectly. The z-order of the elements in my SVG are incorrectly being rendered.
Issue: There are 3x rectangles (color = white), which are above another rectangle (color=red). These 3x rectangles are positioned to have the same y-axis as the red rectangle behind it and have the same height. Despite this positioning/height, there is a "red" border that seems to be visible on the edge of the white rectangle due to the red rectangle in the back. It seems that z-order or stacking order of the elements in the rendered image is not being respected.
Below is a screenshot of the SVG image open in the Inkscape showing the issue. Even after converting the SVG image to PNG, the z-order issue still existing.
After troubleshooting with the position, I noticed the issue randomly disappears depending on the value of the y-axis position, or SVG image size (pixels/width/height). For example, if you change edit the SVG from y="2.5807" to y="2.5", the issue goes however. However, this is a NOT a feasible solution for my issue, but the exact positing and SVG image size properties is are fixed can shouldn't be changed.
Updates
I tried #Robert Longson suggestion of using shape-rendering="crispEdges" on the root SVG. It did NOT solve the issue for my use case. Using his suggestion, it does solve the issue on how the image is rendered in a browser, however the issue is still visible in Inkscape or when SVG is converted to PNG. For my use case, I care about how the SVG is rendered after being converted to PNG.
I just found out shape-rendering="crispEdges does work when SVG is converted to PNG, but its dependent on how the conversion process works. If I use rsvg-convert command in Bash, which is provided by librsvg2-bin, to convert the SVG to PNG, the issue is fixed. However, if I use convert command in Bash, which is provided by ImageMagick, the issue still exist. If open the SVG file in Inkscape and then Export as PNG, then the issue still exist.
<svg baseProfile="full" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink" width="912px" height="1140px" preserveAspectRatio="none" viewBox="0,0,8.0,5.0">
<rect x="0" y="0" width="8.0" height="5.0" fill="white" />
<rect x="0" y="2.5807" width="8.0" height="1.0" fill="red" />
<g transform="translate(2.9275,0)">
<rect x="0" y="2.5807" width="0.5" height="1.0" fill="white" />
<rect x="1.0" y="2.5807" width="1.0" height="1.0" fill="white" />
<rect x="2.5" y="2.5807" width="1.5" height="1.0" fill="white" />
</g>
</svg>
that's antialiasing you can turn it off with shape-rendering="crispEdges"
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="912px" height="1140px" preserveAspectRatio="none" viewBox="0,0,8.0,5.0" shape-rendering="crispEdges">
<rect x="0" y="0" width="8.0" height="5.0" fill="white" />
<rect x="0" y="2.5807" width="8.0" height="1.0" fill="red" />
<g transform="translate(2.9275,0)">
<rect x="0" y="2.5807" width="0.5" height="1.0" fill="white" />
<rect x="1.0" y="2.5807" width="1.0" height="1.0" fill="white" />
<rect x="2.5" y="2.5807" width="1.5" height="1.0" fill="white" />
</g>
</svg>

How to drag complex SVG?

I have the following svg
<g id="end" transform="translate(125,125)">
<path fill="#4DB3B3" d="M50,2.333C23.674,2.333,2.333,23.674,2.333,50S23.674,97.667,50,97.667S97.667,76.326,97.667,50S76.326,2.333,50,2.333z
M82.771,58.973H17.229c-0.862,0-1.561-0.699-1.561-1.561V42.587c0-0.862,0.699-1.561,1.561-1.561h65.542
c0.862,0,1.561,0.699,1.561,1.561v14.825C84.332,58.274,83.633,58.973,82.771,58.973z"/>
<title>End</title>
</g>
The generated svg looks like
If I were to drag from the blue area the dragging works fine.
The only issue I am facing is whenever I try to drag from the center (white area), the event listener doesn't fire. As if the white area in the middle is not part of the SVG.
How can I tackle this issue ?
As if the white area in the middle is not part of the SVG.
Because it's not part of SVG :) The white area inside is the page background. You could try to put something filled inside (like a white rectangle)?
<g id="end" transform="translate(125,125)">
<rect x="10" y="40" width="80" height="20" style="fill:#fff"></rect>
<path fill="#4DB3B3" d="M50,2.333C23.674,2.333,2.333,23.674,2.333,50S23.674,97.667,50,97.667S97.667,76.326,97.667,50S76.326,2.333,50,2.333z
M82.771,58.973H17.229c-0.862,0-1.561-0.699-1.561-1.561V42.587c0-0.862,0.699-1.561,1.561-1.561h65.542
c0.862,0,1.561,0.699,1.561,1.561v14.825C84.332,58.274,83.633,58.973,82.771,58.973z"/>
<title>End</title>
</g>

Avoiding the aliasing / thin "bleed between touching elements

I have an svg which has multiple stroked paths, and a rectangle shape behind them that has the shape of the paths cut out of them. Effectively, the stroked paths should be "plugging the holes" in the rectangle shape.
The reason for this is that I would like to animate the paths so that they are erased, revealing what is underneath through the holes in the rectangle shape.
That's all well and good, and the animation works fine. The problem is that there is a hairline-thin space between the holes and the outside of the path strokes, so you can see what is underneath even while the paths are still there. You can see a screen capture of that here:
How do I avoid this happening? The space is not in the svg, because making it bigger on the page still has the space hairline thin:
I figure it has something to do with the aliasing, but have no idea how to combat it. I can't just apply a thicker stroke to the paths, because then the stroke starts to bleed into the other shapes, as seen here:
What else is there to do?
You could use a mask instead of a clip-path, since masks allow using the stroke to define the masked area.
<mask id="strokemask" maskContentUnits="objectBoundingBox"
x="0" y="0" width="100%" height="100%">
<circle cx="0.5" cy="0.5" r="0.1" stroke="white" fill="white"
stroke-width="0.02"/>
<circle cx="0.5" cy="0.5" r="0.15" stroke="white" fill="none"
stroke-width="0.03"/>
<circle cx="0.5" cy="0.5" r="0.22" stroke="white" fill="none"
stroke-width="0.05"/>
<circle cx="0.5" cy="0.5" r="0.3" stroke="white" fill="none"
stroke-width="0.06"/>
</mask>
Here's a live example of an animated mask that uses some stroked circles.

Creating one shape inside another

We can create shapes like rectangle, circle etc. Can we create a rectangle inside another rectangle?
You can't create a rectangle inside an other rectangle. But you can make 2 rectangles to look so.
You use the <rect> tag for rectangles. By looking at the rectangle description in the specifications, you can see that the content model don't allow <rect> to contain an other <rect> (or shape).
An example of what you can do :
<rect x="0" y="0" width="200" height="100"/>
<rect x="25" y="25" width="150" height="50"/>
You can also add a <g> around those two rectangles to group them, like this :
<g>
<rect x="0" y="0" width="200" height="100"/>
<rect x="25" y="25" width="150" height="50"/>
</g>
More explanations here : http://www.w3.org/TR/SVG/struct.html#Groups
You also have the alternative of using a path to draw 2 rectangles with only one tag. It all depend of your needs.

Resources