SVG: tspan element x attribute not taking absolute position - svg

X attribute is absolute X coordinate for the tspan element. But we check the output is taking more pixels.
Instead of tspan element needs to draw from 30 pixels but it is drawn from 39pixes. Why is it like this? My expectation is that it has to draw from 30 pixels
enter image description here
<svg height="30" width="200">
<text x="0" y="15" fill="red">I love SVG!
<tspan x="30" y="20"fill="blue">Sub Elemenent Text!</tspan>
</text>
</svg>

I'm not able to reproduce the problem. It looks like <tspan> is at the absolute position. I changed the first letter to be "I" for both elements and x for <text> to 10. It looks right to me.
<svg viewBox="0 0 200 30">
<line x1=".2" y1="0" x2=".2" y2="30" stroke="gray" stroke-width=".4"/>
<line x1="10" y1="0" x2="10" y2="30" stroke="gray" stroke-width=".4"/>
<line x1="20" y1="0" x2="20" y2="30" stroke="gray" stroke-width=".4"/>
<line x1="30" y1="0" x2="30" y2="30" stroke="gray" stroke-width=".4"/>
<text x="10" y="15" fill="red">I love SVG!
<tspan x="30" y="20"fill="blue">I'm Elemenent Text!</tspan>
</text>
</svg>

Related

How to color a region i.e the intersection of two object?

I want to color an intersection of two object, let's say a circle and a rectangle.
What I have tried so far is to defined a path bounding that region then add the fill attribute, but it seems too complicated.
Is there any other ways to do so?
Let me elabotare more one the problem:
<svg width="352" height="57" xmlns="http://www.w3.org/2000/svg">
<line y2="0.75" x2="103.95" y1="43.15" x1="42.35" stroke-width="1.5" stroke="#000" fill="none"/>
<line y2="50.35" x2="201.55" y1="0.75" x1="103.95" stroke-width="1.5" stroke="#000" fill="none"/>
<line y2="19.15" x2="239.95" y1="49.55" x1="201.55" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" stroke="#000" fill="none"/>
<line y2="55.95" x2="282.35" y1="18.35" x1="240.75" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" stroke="#000" fill="none"/>
<line y2="37.55" x2="351.15" y1="31.95" x1="0.75" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" stroke="#000" fill="none"/>
</svg>
I have a set of lines which the end of one is another end of the other.
I have another line intersecing these line.
How could I color the region i.e the triangles formed by these line?
You can use <clipPath> to clip the rect with the circle like so:
svg{width:100vh;}
<svg viewBox="50 50 200 100">
<clipPath id="clip">
<use xlink:href="#c" />
</clipPath>
<g fill="none" stroke="black" >
<circle id="c" cx="100" cy="100" r="30" />
<rect id="r" x="90" y="80" width="80" height="60" />
</g>
<use xlink:href="#r" clip-path="url(#clip)" fill="gold" />
</svg>
You could work with opacity to let the color of an overlapped element shine through like shown here:
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg">
<g style="stroke:#000; stroke-width:1">
<circle cx="50" cy="50" r="50" opacity="0.5" style="fill:red" />
<circle cx="100" cy="50" r="50" opacity="0.5" style="fill:yellow" />
<rect x="0" y="70" width="150" height="50" fill-opacity="0.5" style="fill:blue" />
</g>
</svg>
You can also specify the opacity levels separately for stroke and fill by using stroke-opacity and fill-opacity.
Edit:
Looking at your edited question again: when you are dealing with a succession of lines (and curves) you should use <path> elements instead of individual <line> elements. One of its advantages is that it comes with a fill behaviour that is almost exactly as you want it to be. However, to suit the requirements of your example you would need to find the positions where the straight line enters and leaves the zig-zag shape. These positions then define the points used for your filled path. The "original" (non-filled) path is then plotted over the filled path:
<svg width="352" height="57" xmlns="http://www.w3.org/2000/svg">
<path d="M56,33 103.95,0.75 201.55,50.35 239.95,19.15 260,36z
M0.75,31.95 351.15,37.55" style="fill:yellow" />
<path d="M42.35,43.15 103.95,0.75 201.55,50.35 239.95,19.15 282.35,55.95
M0.75,31.95 351.15,37.55" style="stroke:black;fill:none"/>
</svg>

Responsive svg with percentage and pixel values

I can create a svg with line at any given percentage "0%-100%" so that the rounded borders (in pixels) are not included in the "percentage width" with the help of calc calc(100% - 25px)
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="50">
<rect fill="lightblue" y="0" x="0" width="100%" height="50" rx="25" ry="25"></rect>
<g class="percentage">
<line class="100pct" x1="calc(100% - 25px)" x2="calc(100% - 25px)" y1="0" y2="50" stroke="red" stroke-width="4"></line>
</g>
</svg>
But the question is, can this same svg be created without calc for legacy browsers?
I can use transform and translate to take one rounded side into account, but I can't figure out how to limit the width / add some kind of margin.
The percentage change, so one shared translate gets me only halfway there, here the red 100% line is out of bounds:
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="50">
<rect fill="lightblue" y="0" x="0" width="100%" height="50" rx="25" ry="25"></rect>
<g class="percentage" transform="translate(25, 0)">
<line class="0pct" x1="0%" x2="0%" y1="0" y2="50" stroke="blue" stroke-width="4"></line>
<line class="100pct" x1="100%" x2="100%" y1="0" y2="50" stroke="red" stroke-width="4"></line>
</g>
</svg>
Is there really any browser supporting the above syntax? If yes, it is in violation of even the SVG2 spec:
A future specification may convert the ‘x1’, ‘y1’, ‘x2’, and ‘y2’ attributes to geometric properties. Currently, they can only be specified via element attributes, and not CSS.
(And since calc() is a CSS function, it can only be used in CSS contexts.)
What will work in all browsers supporting SVG is to combine x/y values with transforms; unitless = px values go to the transform attribute, units (percentages) go to the x/y attribute.
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="50">
<rect fill="lightblue" y="0" x="0" width="100%" height="50" rx="25" ry="25"></rect>
<g class="percentage" >
<line class="0pct" x1="100%" x2="100%" y1="0" y2="50" transform="translate(-25, 0)" stroke="red" stroke-width="4"></line>
</g>
</svg>
In addition to the SVG 1.1 transform attribute, there is also the CSS transform property and its 2D functions which are implemented quite fairly (exeption: IE and Edge < 17). They must use unit identifiers, and should also support nested calc() functions. I have no compatibility data for that combination, but there are also no bug reports mentioned in caniuse.com.
What currently does not work is using the CSS transform syntax as a presentation attribute (CSS transform spec is not yet implemented in that regard), so you need to use them in style attributes.
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="50">
<rect fill="lightblue" y="0" x="0" width="100%" height="50" rx="25" ry="25"></rect>
<g class="percentage" stroke="red" stroke-width="4" >
<line class="0pct" x1="0" x2="0" y1="0" y2="50"
style="transform:translate(calc(0 * (100% - 50px) + 25px))" />
<line class="50pct" x1="0" x2="0" y1="0" y2="50"
style="transform:translate(calc(0.5 * (100% - 50px) + 25px))" />
<line class="100pct" x1="0" x2="0" y1="0" y2="50"
style="transform:translate(calc(1 * (100% - 50px) + 25px))" />
</g>
</svg>
As you can see, the positional value is no longer a percentage (multiplying pixels with percentages does not work), but a fraction of 1. I hope that works for you.

why the text path are not rendered?

I really got puzzled why these two text are not displayed along the line and path. Could someone point me out?
<svg width="300px" height="300px">
<line id="ok" x1="10" y1="20" x2="100" y2="100" stroke="red" stroke-width=10>
<text>
<textPath stroke="black" xlink:href="#ok">OHHHHSUHDIAU</textPath>
</text>
</line>
<path id="io" d="M10,10 L100,10" stroke="blue" stroke-width=10>
<text>
<textPath stroke="black" xlink:href="#io">io</textPath>
</text>
</path>
</svg>
you can only do a <textPath> on a <path>
placing the <text> inside the <line> or <path> elements were causing them not to be rendered.
here is my best guess at what you're trying to accomplish, I hope this helps
<svg width="300px" height="300px">
<defs>
<path id="io" d="M10,10 L100,10" />
<path id="ok" d="M10,20 L100,100" />
</defs>
<use xlink:href="#io" stroke-width="10" stroke="blue" />
<use xlink:href="#ok" stroke-width="10" stroke="red" />
<text>
<textPath stroke="black" xlink:href="#io">io</textPath>
<textPath stroke="black" xlink:href="#ok">OHHHHSUHDIAU</textPath>
</text>
</svg>

Inkscape: svg dominant-baseline property not interpreted

Inkscape doesnt seem to interpret the svg dominant-baseline property.
I try to rotate a svg text in its center, both vertical and horizontal. In html (chrome) the following works well:
<html>
<body>
<svg width="1000" height="1000" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<line x1="10" y1="10" x2="190" y2="190" style="stroke:red;stroke-width:2"></line>
<line x1="10" y1="190" x2="190" y2="10" style="stroke:red;stroke-width:2"></line>
<g transform="translate(100,100)"><g transform="rotate(0)">
<text style="font-family:Roboto; font-size:100;" fill="blue" text-anchor="middle" dominant-baseline="central">04</text></g></g>
<line x1="310" y1="10" x2="490" y2="190" style="stroke:red;stroke-width:2"></line>
<line x1="310" y1="190" x2="490" y2="10" style="stroke:red;stroke-width:2"></line>
<g transform="translate(400,100)"><g transform="rotate(90)">
<text style="font-family:Roboto; font-size:100;" fill="blue" text-anchor="middle" dominant-baseline="central">04</text></g></g>
</svg>
</body>
</html>
which result in the following graphic:
text rotation in html
When i extract the svg tag element and put it in a stand alone svg file, Inkscape doesnt seem to interpret the
dominant-baseline="central"
property.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns="http://www.w3.org/2000/svg" height="1000" width="1000">
<line x1="10" y1="10" x2="190" y2="190" style="stroke:red;stroke-width:2"></line>
<line x1="10" y1="190" x2="190" y2="10" style="stroke:red;stroke-width:2"></line>
<g transform="translate(100,100)"><g transform="rotate(0)">
<text style="font-family:Roboto; font-size:100;" fill="blue" text-anchor="middle" dominant-baseline="central">04</text></g></g>
<line x1="310" y1="10" x2="490" y2="190" style="stroke:red;stroke-width:2"></line>
<line x1="310" y1="190" x2="490" y2="10" style="stroke:red;stroke-width:2"></line>
<g transform="translate(400,100)"><g transform="rotate(90)">
<text style="font-family:Roboto; font-size:100;" fill="blue" text-anchor="middle" dominant-baseline="central">04</text></g></g>
</svg>
text rotation in inkscape
Any suggestion how to achieve the same result in inkscape highly appreciated.

How to make an SVG "line" with a border around it?

I have a little svg widget whose purpose is to display a list of angles (see image).
Right now, the angles are line elements, which only have a stroke and no fill. But now I'd like to have an "inside fill" color and a "stroke/border" around it. I'm guessing the line element can't handle this, so what should I use instead?
Notice that the line-endcap of the line's stroke is rounded. I'd like to maintain this effect in the solution.
<svg height="160" version="1.1" viewBox="-0.6 -0.6 1.2 1.2" width="160" xmlns="http://www.w3.org/2000/svg">
<g>
<g>
<circle class="sensorShape" cx="0" cy="0" fill="#FFF" r="0.4" stroke="black" stroke-width="0.015"/>
<line stroke="black" stroke-width="0.015" x1="0" x2="0" y1="-0.4" y2="0.4"/>
<line stroke="black" stroke-width="0.015" x1="-0.4" x2="0.4" y1="0" y2="0"/>
</g>
<g class="lsNorthAngleHandsContainer">
<line data-angle="348" stroke="red" stroke-linecap="round" stroke-width="0.04" transform="rotate(348)" x1="0" x2="0" y1="0" y2="-0.4"/>
<text font-size="0.08" transform="translate(-0.02316467632710395,-0.45125904029352226)">
348
</text>
</g>
</g>
</svg>
Add a second line, with same coordinates but thinner line width:
<g class="lsNorthAngleHandsContainer">
<line data-angle="348" stroke="red" stroke-linecap="round" stroke-width="0.04" transform="rotate(348)" x1="0" x2="0" y1="0" y2="-0.4"/>
<line data-angle="348" stroke="yellow" stroke-linecap="round" stroke-width="0.025" transform="rotate(348)" x1="0" x2="0" y1="0" y2="-0.4"/>
I found elegant solution inspired by illustration to W3C article about filling and stroking. Basically, you move path to definitions and use this definition to draw two elements:
<svg width="200" height="200" viewBox="0 0 100 100">
<defs>
<line id="line1" x1="25" x2="75" y1="25" y2="75"/>
</defs>
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#line1" class="stroke"></use>
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#line1" class="line"></use>
</svg>
By using <defs> and <use> you can change only path element to update both lines. JSFiddle demo
It looks like your line is opaque, so you can just draw a thin line with the "inside" color on top of the thicker line with the "outside" color.
You could use a rect with rounded corners, but the math changes a bit:
<rect data-angle="348" stroke="red" stroke-linecap="round" stroke-width="0.02" fill="#FF0" transform="rotate(348, 0, 0)" x="-0.02" y="-0.4" width=".06" height=".4" rx=".03" ry=".03"/>
http://jsfiddle.net/RNAuP/
You can also do it with a path, even though it's tricky around the round bits:
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!-- I often use entities to be able to change lot of numbers at once in static SVG, also kind of makes the paths more readable.
Obvisouly, if you're generating the path you can use the same variables in code to append to d -->
<!ENTITY handFill "0.01">
<!ENTITY handFill2 "0.02"><!-- Should be 2 * handFill to be centered -->
<!ENTITY handStroke "0.005"><!-- Should be less than handFill2 to not hide fill -->
]>
<svg height="160" version="1.1" viewBox="-0.6 -0.6 1.2 1.2" width="160" xmlns="http://www.w3.org/2000/svg">
<g>
<g>
<circle class="sensorShape" cx="0" cy="0" fill="#FFF" r="0.4" stroke="black" stroke-width="0.015"/>
<line stroke="black" stroke-width="0.015" x1="0" x2="0" y1="-0.4" y2="0.4"/>
<line stroke="black" stroke-width="0.015" x1="-0.4" x2="0.4" y1="0" y2="0"/>
</g>
<g class="lsNorthAngleHandsContainer">
<path d="
M -&handFill;,0 l0,-0.4
a &handFill;,&handFill; 0 0,1 &handFill2;,0
l 0,0.4
a &handFill;,&handFill; 0 0,1 -&handFill2;,0
" stroke="red" stroke-linecap="round" stroke-width="&handStroke;" fill="yellow" transform="rotate(348)" />
<text font-size="0.08" transform="translate(-0.02316467632710395,-0.45125904029352226)">
348
</text>
</g>
</g>
</svg>

Resources