why the text path are not rendered? - svg

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>

Related

SVG text textlength not working on Mobile Safari

Noticed my SVG text was looking different on different browsers.
After some testing, found that Mobile Safari isn't respecting textLength set on an svg text element.
<text dy="10" textLength="240" fill="red">
Here is the SVG code.
<svg class="passportStamp stampEffectClass" width="120" height="120" viewBox="0 0 206 206">
<circle cx="103" cy="103" r="100" fill="none" stroke="red" stroke-width="3"></circle>
<circle cx="103" cy="103" r="90" fill="none" stroke="red" stroke-width="3"></circle>
<text x="103" y="70" text-anchor="middle" fill="red" stroke-width="2px" alignment-baseline="middle" font-variant="all-small-caps" font-size="31" font-weight="bold">textLength</text>
<text x="103" y="100" text-anchor="middle" fill="red" alignment-baseline="middle" font-variant="all-small-caps" font-size="45">100</text>
<path id="textCircle" d="M28,103a75,75 0 1,0 150,0a75,75 0 1,0 -150,0" fill="none" stroke="none"></path>
<text dy="10" textLength="240" fill="red">
<textPath xlink:href="#textCircle">textLength Chrome vs iOS</textPath>
</text>
<g fill="red" transform="scale(0.15) translate(550 800)">
<path d="m2,106h28l24,30h72l-44,-133h35l80,132h98c21,0 21,34 0,34l-98,0 -80,134h-35l43,-133h-71l-24,30h-28l15,-47"></path>
</g>
<g fill="red" transform="translate(90,30)">
<path d="M14.128 1.79003C13.1305"></path>
</g>
</svg>
Looking at cross browser fallback options, but haven't found any way to make it work yet.
Found the problem. Safari wants the textlength to be set on the textPath.
Solution, set the textlength on both the text for Chrome, and textPath for Safari.
Was tipped off by this issue on the great github project webcompat, which reported similar issues.
Code:
<svg width="205" height="205" class="stampEffectClass isolate">
<circle cx="103" cy="103" r="100" fill="none" stroke="red" stroke-width="3"></circle>
<circle cx="103" cy="103" r="90" fill="none" stroke="red" stroke-width="3"></circle>
<text x="103" y="70"
text-anchor="middle" fill="red" stroke-width="2px" alignment-baseline="middle" font-variant="all-small-caps"
font-size="45" font-weight="bold">textLength</text>
<text x="103" y="100" text-anchor="middle" fill="red"
alignment-baseline="middle" font-variant="all-small-caps" font-size="45">240</text>
<path id="textCircle" d="M28,103a75,75 0 1,0 150,0a75,75 0 1,0 -150,0" fill="none" stroke="none"></path>
<text dy="10"
textLength="240" fill="red">
<textPath xlink:href="#textCircle" textLength="240">textLength Chrome vs iOS</textPath>
</text>
<g fill="red" transform="scale(0.15) translate(550 800)">
<path d="m2,106h28l24,30h72l-44,-133h35l80,132h98c21,0 21,34 0,34l-98,0 -80,134h-35l43,-133h-71l-24,30h-28l15,-47">
</path>
</g>
<g fill="red" transform="translate(90,30)">
<path
d="M14.128 1.79003C13.1305">
</path>
</g>
</svg>
Image showing fix:

SVG using non-repetitive pattern as fill

I'm trying to use different SVG elements with a pattern as a fill, but the pattern doesn't get repeated for every element. I'm not sure if there's the possibility to repeat the pattern, but right now it looks as if there's a pattern and three circles create a mask over the pattern. What I want to achieve is the three circles clearly looking differently because each pattern resets for each circle and then it doesn't look 'cut out'.
I suppose a last-resort solution would be to create multiple patterns with different names for every element I use, then it'll work, but I'm hoping there's a less cumbersome way.
I tried:
Wrapping each element in a different SVG container
Appending ids to the elements and then in css target every id separately with the fill being the url
I made a codesandbox which shows my problem:
https://codesandbox.io/s/busy-ives-hv3rr?file=/index.html
The solution #herrstrietzel posted is one way to go.
Another solution is to create variants of your original pattern, but with a different origin. You specify the origin using the x and y attributes.
<svg id="patternId" width="100%" height="100%">
<defs>
<pattern id="a" patternUnits="userSpaceOnUse" width="65" height="65" patternTransform="scale(2) rotate(0)">
<rect x="0" y="0" width="100%" height="100%" fill="hsla(0,0%,100%,1)"/>
<path d="M.5.5v12h12V.5H.5zm13 13v12h12v-12h-12zm-13 13v12h12v-12H.5zm26 13v12h12v-12h-12zm13 13v12h12v-12h-12z"
stroke-width="1" stroke="none" fill="hsla(258.5,59.4%,59.4%,1)"/>
<path d="M26.5.5v12h12V.5h-12zm0 13v12h12v-12h-12zm13 13v12h12v-12h-12zm-39 13v12h12v-12H.5zm0 13v12h12v-12H.5z"
stroke-width="1" stroke="none" fill="hsla(339.6,82.2%,51.6%,1)"/>
<path d="M13.5.5v12h12V.5h-12zm39 13v12h12v-12h-12zm-39 13v12h12v-12h-12zm39 0v12h12v-12h-12zm-26 26v12h12v-12h-12z"
stroke-width="1" stroke="none" fill="hsla(198.7,97.6%,48.4%,1)"/>
<path d="M52.5.5v12h12V.5h-12zm-13 13v12h12v-12h-12zm0 26v12h12v-12h-12zm13 0v12h12v-12h-12zm-39 13v12h12v-12h-12z"
stroke-width="1" stroke="none" fill="hsla(33, 90%, 65%, 1)"/>
</pattern>
<pattern id="a2" href="#a" x="20" y="20"/>
<pattern id="a3" href="#a" x="45" y="50"/>
</defs>
<svg height="200" width="200">
<circle cx="50" cy="50" r="40" fill="url(#a)" />
</svg>
<svg height="200" width="200">
<circle cx="100" cy="50" r="40" fill="url(#a2)" />
</svg>
<svg height="200" width="200">
<circle cx="50" cy="100" r="40" fill="url(#a3)" />
</svg>
</svg>
Another alternative is to switch to objectBoundingBox units. So that the pattern is relative the the object it is applied to.
<svg id="patternId" width="100%" height="100%">
<defs>
<pattern id="a" patternUnits="objectBoundingBox" width="65" height="65">
<g transform="scale(2)">
<rect x="0" y="0" width="100%" height="100%" fill="hsla(0,0%,100%,1)"/>
<path d="M.5.5v12h12V.5H.5zm13 13v12h12v-12h-12zm-13 13v12h12v-12H.5zm26 13v12h12v-12h-12zm13 13v12h12v-12h-12z"
stroke-width="1" stroke="none" fill="hsla(258.5,59.4%,59.4%,1)"/>
<path d="M26.5.5v12h12V.5h-12zm0 13v12h12v-12h-12zm13 13v12h12v-12h-12zm-39 13v12h12v-12H.5zm0 13v12h12v-12H.5z"
stroke-width="1" stroke="none" fill="hsla(339.6,82.2%,51.6%,1)"/>
<path d="M13.5.5v12h12V.5h-12zm39 13v12h12v-12h-12zm-39 13v12h12v-12h-12zm39 0v12h12v-12h-12zm-26 26v12h12v-12h-12z"
stroke-width="1" stroke="none" fill="hsla(198.7,97.6%,48.4%,1)"/>
<path d="M52.5.5v12h12V.5h-12zm-13 13v12h12v-12h-12zm0 26v12h12v-12h-12zm13 0v12h12v-12h-12zm-39 13v12h12v-12h-12z"
stroke-width="1" stroke="none" fill="hsla(33, 90%, 65%, 1)"/>
</g>
</pattern>
<pattern id="a2" href="#a" x="20" y="20"/>
<pattern id="a3" href="#a" x="45" y="50"/>
</defs>
<svg height="200" width="200">
<circle cx="50" cy="50" r="40" fill="url(#a)" />
</svg>
<svg height="200" width="200">
<circle cx="100" cy="50" r="40" fill="url(#a)" />
</svg>
<svg height="200" width="200">
<circle cx="50" cy="100" r="40" fill="url(#a)" />
</svg>
</svg>
Applying transforms like transform="translate(50 50)" (instead of fixed x/y positioning would do the trick.
<svg id="patternId" width="100%" height="100%">
<defs>
<pattern id="pattern-0" patternUnits="userSpaceOnUse" width="65" height="65" patternTransform="scale(2) rotate(0)" >
<g id="patternInner">
<rect x="0" y="0" width="100%" height="100%" fill="hsla(0,0%,100%,1)" />
<path d="M.5.5v12h12V.5H.5zm13 13v12h12v-12h-12zm-13 13v12h12v-12H.5zm26 13v12h12v-12h-12zm13 13v12h12v-12h-12z" stroke-width="1" stroke="none" fill="hsla(258.5,59.4%,59.4%,1)" />
<path d="M26.5.5v12h12V.5h-12zm0 13v12h12v-12h-12zm13 13v12h12v-12h-12zm-39 13v12h12v-12H.5zm0 13v12h12v-12H.5z" stroke-width="1" stroke="none" fill="hsla(339.6,82.2%,51.6%,1)" />
<path d="M13.5.5v12h12V.5h-12zm39 13v12h12v-12h-12zm-39 13v12h12v-12h-12zm39 0v12h12v-12h-12zm-26 26v12h12v-12h-12z" stroke-width="1" stroke="none" fill="hsla(198.7,97.6%,48.4%,1)" />
<path d="M52.5.5v12h12V.5h-12zm-13 13v12h12v-12h-12zm0 26v12h12v-12h-12zm13 0v12h12v-12h-12zm-39 13v12h12v-12h-12z" stroke-width="1" stroke="none" fill="hsla(33, 90%, 65%, 1)" />
</g>
</pattern>
<pattern id="pattern-1" href="#pattern-0" x="80" y="80" patternTransform="scale(2) rotate(45)" />
</defs>
<circle cx="50" cy="50" r="40" fill="url(#pattern-0)" />
<circle cx="50" cy="50" r="50" fill="url(#pattern-0)" transform="translate(50 33)" />
<circle cx="50" cy="50" r="50" fill="url(#pattern-1)" transform="translate(50 33)" />
<rect x="0" y="0" width="50" height="50" stroke="#fff" stroke-width="1" transform="translate(10 60)" fill="url(#pattern-0)" />
</svg>
Worth noting: duplicating patterns for slightly modified usage is pretty straight forward, since the <pattern> element supports referencing/reusing previously defined patterns via href attribute (similar to <use>):
<pattern id="pattern-1" href="#pattern-0" x="80" y="80" patternTransform="scale(2) rotate(45)" />
Would result in a rotated pattern sharing all properties of the initially defined pattern.

What is the data-value attribute in SVG?

I was looking at this article
And particularly this code,
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="graph" aria-labelledby="title" role="img">
<title id="title">A line chart showing some information</title>
<g class="grid x-grid" id="xGrid">
<line x1="90" x2="90" y1="5" y2="371"></line>
</g>
<g class="grid y-grid" id="yGrid">
<line x1="90" x2="705" y1="370" y2="370"></line>
</g>
<g class="labels x-labels">
<text x="100" y="400">2008</text>
<text x="246" y="400">2009</text>
<text x="392" y="400">2010</text>
<text x="538" y="400">2011</text>
<text x="684" y="400">2012</text>
<text x="400" y="440" class="label-title">Year</text>
</g>
<g class="labels y-labels">
<text x="80" y="15">15</text>
<text x="80" y="131">10</text>
<text x="80" y="248">5</text>
<text x="80" y="373">0</text>
<text x="50" y="200" class="label-title">Price</text>
</g>
<g class="data" data-setname="Our first data set">
<circle cx="90" cy="192" data-value="7.2" r="4"></circle>
<circle cx="240" cy="141" data-value="8.1" r="4"></circle>
<circle cx="388" cy="179" data-value="7.7" r="4"></circle>
<circle cx="531" cy="200" data-value="6.8" r="4"></circle>
<circle cx="677" cy="104" data-value="6.7" r="4"></circle>
</g>
</svg>
And I was wondering what data-value attribute was. When I tried googling for some documentation I only found this page, which said:
The data-* SVG attributes are called custom data attributes. They let SVG markup and its resulting DOM share information that standard attributes can't, usually for scripting purposes. Their custom data are available via the SVGElement interface of the element the attributes belong to, with the SVGElement.dataset property.
And since I'm new at SVG, I wasn't sure what this meant. If someone could elucidate me on what data-value is that would be great!

Why is my shape not rotating along its apparent bounding box?

I'm trying to rotate this image (#small) so that it's upside down, but the shape isn't rotating as I'd expect. It seems to me that the bounding box would be much smaller than its apparent axis of rotation.
What's actually going on here and how can I fix it?
MWE
<?xml version="1.0" encoding="utf-8"?>
<svg id="test-image"
viewBox="0 0 816 1110"
width="816" height="1110"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<g id="base">
<svg viewBox="-8 -10 16 20" >
<path d="M 7.989,3.103 C 7.747,-0.954 0.242,-8.59 0,-10.5 c -0.242,1.909 -7.747,9.545 -7.989,13.603 -0.169,2.868 1.695,4.057 3.39,4.057 1.8351685,-0.021581 3.3508701,-2.8006944 3.873,-3.341 0.242,0.716 -1.603,6.682 -2.179,6.682 l 5.811,0 C 2.33,10.501 0.485,4.535 0.727,3.819 1.1841472,4.3152961 2.5241276,7.0768295 4.601,7.16 6.295,7.159 8.158,5.971 7.989,3.103 z"
style="fill:#000000" />
</svg>
</g>
<g id="small">
<use xlink:href="#base" transform="scale(0.1,0.1)" />
</g>
</defs>
<!-- debugging grid -->
<rect width="100%" height="100%" stroke="black" fill="white"/>
<rect width="80%" height="80%" stroke="lightgrey" fill="white" x="10%" y="10%" />
<rect width="60%" height="60%" stroke="lightgrey" fill="white" x="20%" y="20%" />
<rect width="40%" height="40%" stroke="lightgrey" fill="white" x="30%" y="30%" />
<rect width="20%" height="20%" stroke="lightgrey" fill="white" x="40%" y="40%" />
<line x1="0%" x2="100%" y1="50%" y2="50%" stroke="lightgrey" />
<line y1="0%" y2="100%" x1="50%" x2="50%" stroke="lightgrey" />
<!-- rotation test -->
<use xlink:href="#small" x="50%" y="50%" />
<use xlink:href="#small" x="50%" y="50%" transform="rotate(10)" />
<use xlink:href="#small" x="50%" y="50%" transform="rotate(20)" />
<use xlink:href="#small" x="50%" y="50%" transform="rotate(30)" />
</svg>

reusable parameters/ variables for svg graphic

For a study project I'm asked to write an easy customizable svg graphic.
Is there any concept of variables?
The best I came up with so far is the following:
<g id="box">
<rect x="0" y="0" width="25" height="20" rx="3" ry="3" style="fill:transparent;stroke-width:1;stroke:rgb(0,0,0)">
</g>
<g id="month">
<!-- first row -->
<g transform="translate(50 40)">
<use xlink:href='#box'/>
<text x="5" y="15" fill="grey">Monday</text>
</g>
<g transform="translate(75 40)">
<use xlink:href='#box'/>
<text x="5" y="15" fill="grey">Tuesday</text>
</g>
<g transform="translate(100 40)">
<use xlink:href='#box'/>
<text x="5" y="15" fill="grey">Wednesday</text>
</g>
<g transform="translate(125 40)">
<use xlink:href='#box'/>
<text x="5" y="15" fill="grey">Thursday</text>
</g>
<g transform="translate(150 40)">
<use xlink:href='#box'/>
<text x="5" y="15" fill="grey">Friday</text>
</g>
<g transform="translate(175 40)">
<use xlink:href='#box'/>
<text x="5" y="15" fill="grey">Saturday</text>
</g>
<g transform="translate(200 40)">
<use xlink:href='#box'/>
<text x="5" y="15" fill="grey">Sunday</text>
</g>
....
</g>
Now the problem is, that if I change the the width of the box I need to adjust the translate parameter for each element in the month group.
Would be great to have something like this:
<param name="box-height" value="20" />
<param name="box-width" value="25" />
<g id="box">
<rect x="0" y="0" width="box-width" height="box-height" rx="3" ry="3" style="fill:transparent;stroke-width:1;stroke:rgb(0,0,0)">
</g>
<g id="month">
<!-- first row -->
<g transform="translate(2*box-width 40)">
<use xlink:href='#box'/>
<text x="5" y="15" fill="grey">Monday</text>
</g>
<g transform="translate(3*box-width 40)">
<use xlink:href='#box'/>
<text x="5" y="15" fill="grey">Tuesday</text>
</g>
...
</g>
But I didnt find anything so far. Does something like this exist, or any other helpful ideas.
Thank you.
The answer is no.
Parameters have been suggested in the past, and have even had draft specs written, but haven't made it to any implementation of SVG AFAIK.
However you can create and manipulate SVG elements with Javascript. You can use plain old JS, or one of the specialty libraries like d3 or Raphaels.

Resources