canvas in foreignObject in defs/use not displayed - svg

I want to use JavaScript to draw on an html5 canvas embedded in svg (in an html5 page). Drawing on "cvs" works just fine if done this way:
<svg id="fig" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1024px" height="1024px" viewBox="0 0 1024 1024">
<foreignObject x="0" y="0" width="512" height="512">
<body xmlns="http://www.w3.org/1999/xhtml">
<canvas id="cvs" width="512" height="512"></canvas>
</body>
</foreignObject>
</svg>
but not if done with the canvas in and referred to in a use tag. The drawing simply doesn't appear. Inspecting the element in Safari tells me that the the dimensions of the use element are NaN x NaN; Firebug says 0x0.
<svg id="fig" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1024px" height="1024px" viewBox="0 0 1024 1024">
<defs>
<foreignObject id="circles" x="0" y="0" width="512" height="512">
<body xmlns="http://www.w3.org/1999/xhtml">
<canvas id="cvs" width="512" height="512"></canvas>
</body>
</foreignObject>
</defs>
<use x="0" y="0" xlink:href="#circles"></use>
</svg>
Is this a bug? Expected behavior? Do I just not understand how to use foreignObject (highly likely)?

You can't point to a foreignObject element directly, it says so in the SVG specification
‘svg’, ‘symbol’, ‘g’, graphics element or other ‘use’ only. So you could point to a <g> or <svg> element that had a <foreignObject> element as a child for instance.

Related

Cannot change the size of a use SVG element

this is the raw code I've received. Just a cross defined as a polygon :
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 115.9 80" style="enable-background:new 0 0 115.9 80;" xml:space="preserve">
<polygon points="78.8,36.5 70.5,36.5 70.5,28.2 66.5,28.2 66.5,36.5 58.2,36.5 58.2,40.5 66.5,40.5 66.5,48.8 70.5,48.8 70.5,40.5
78.8,40.5 "/>
</svg>
and this is what I've done :
<svg class="icons" version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px">
<symbol id="cross">
<polygon points="78.8,36.5 70.5,36.5 70.5,28.2 66.5,28.2 66.5,36.5 58.2,36.5 58.2,40.5 66.5,40.5 66.5,48.8 70.5,48.8 70.5,40.5 78.8,40.5" style="fill:#6511e4;"/>
</symbol>
</svg>
<div class="cross">
<svg viewBox="0 0 115.9 80" width="15" height="15">
<use href="#cross" id="cross-1"/>
</svg>
</div>
following the solution for the same problem someone else had (Cannot Change SVG <use> icon size when linked to <symbol>)
but this is not working :/ I just want for exemple to resize the cross with a 15px width and 15px height.
Could someone provide me the solution as well as some explanations ? thanks : )
If you encapsulate a SVG drawing in a symbol, the viewBox attribute moves from the <svg> to the <symbol> element.
The viewBox values of your source are not really helpful. A tight bounding box around the grafic can be achieved with viewBox="58.2 28.2 20.6 20.6". You can find it with the original file loaded in a browser. Then do
document.querySelector('polygon').getBBox()
The returned object provides you with x/y/width/height values you can feed into the viewBox.
I'd like to point out there is an implicit sizing going on here: The symbol is shown according to the x/y/width/height values of the <use> element where it is referenced. None of them are present; they default to 0 (position) and 100% (size). In other words: the <use> element just fills its surrounding <svg> element, where width and height are set.
<svg class="icons" width="0px" height="0px">
<symbol viewBox="58.2 28.2 20.6 20.6" id="cross">
<polygon points="78.8,36.5 70.5,36.5 70.5,28.2 66.5,28.2 66.5,36.5 58.2,36.5 58.2,40.5 66.5,40.5 66.5,48.8 70.5,48.8 70.5,40.5 78.8,40.5" style="fill:#6511e4;"/>
</symbol>
</svg>
<div class="cross">
<svg width="15" height="15">
<use href="#cross" id="cross-1"/>
</svg>
</div>

How to refer to values set in the parent document in an element imported via <use>

For a toy project I'm working with random flag designs and random flag colors. Since the paths are a huge chunk of ugly exported SVG, I'd like to have all these shapes put into a library SVG. That way, the generator would only have to create a small, simple-to-read stub to define the colors, and import the designs from the library.
A pair of demonstration files.
flaglib.svg:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
<svg version="1.1" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="500px" height="300px" viewBox="0 0 500 300" xml:space="preserve">
<g id="Design1">
<rect width="500px" height="300px" fill="url(#BACKGROUND_PRIMARY)" />
<circle cx="250px" cy="150px" r="90px" fill="url(#FOREGROUND_PRIMARY)" />
</g>
...
</svg>
flagstub.svg:
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
<svg version="2.0" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" width="500px" height="500px" viewBox="0 0 500 500" xml:space="preserve">
<defs>
<linearGradient id="BACKGROUND_PRIMARY"><stop offset="50%" stop-color="#F00" /></linearGradient>
<linearGradient id="FOREGROUND_PRIMARY"><stop offset="50%" stop-color="#FF0" /></linearGradient>
</defs>
<use href="flaglib.svg#Design1"></use>
</svg>
The tag with the ID #BACKGROUND_PRIMARY is only defined once, so when it imports the missing text before it renders, it shouldn't be pulling a value for that from anywhere else. And yet, they ignore the values set.
So: how can the SVG elements imported from the library file use the colors defined in the stub fule?
What browser(s) are you testing with? Last I checked, only Firefox properly supports external use references.
See this question for more discussion on this topic.

SVG accessibility causing invalid HTML (duplicate ID's)

Have an interesting one for the hive. I've done quite a bit of searching about and haven't found an answer to this on S.O. or elsewhere.
I am working on making our website as accessible as possible, this includes providing text alternatives to non-text content. (WCAG 1.1.1)
So far, we've followed the recommendations of CSS Tricks and Sitepoint
https://www.sitepoint.com/tips-accessible-svg/
https://css-tricks.com/accessible-svgs/
by adding:
role="img"
<title>
<desc>
and aria-labelledby, and providing an id for each <title> and <desc>
This works a treat when there is only one of a particular icon on the page. The problem arises when we have the same icon on the page more than once. Because our SVG's are being inlined, id'ing the <title> and <desc> tags will cause validation errors, which is also a no-no for accessibility. ( WCAG 4.1.1 )
So the question then becomes, how can we make our SVGs accessible while still maintaining valid HTML? My first thought was to pull the title and desc text into an aria-label on the tag, but would that then read twice to non-sighted users? Is it fine to leave off the aria-labelledby? Any help is much appreciated!
The full SVG code as it currently stands:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="120px" height="120px" viewBox="0 0 120 120" enable-background="new 0 0 120 120" xml:space="preserve" role="img" aria-labelledby="rings-svg rings-svg-desc" class="rings">
<title id="rings-svg">Ring</title>
<desc id="rings-svg-desc">An empty circle ring</desc>
<g>
<g>
<path fill="#E5E5E5" d="M60,112.151C31.245,112.151,7.85,88.756,7.85,60C7.85,31.245,31.245,7.851,60,7.851
S112.15,31.245,112.15,60C112.15,88.756,88.755,112.151,60,112.151z M60,9.426C32.113,9.426,9.425,32.113,9.425,60
S32.113,110.576,60,110.576S110.575,87.887,110.575,60S87.887,9.426,60,9.426z"></path>
</g>
<g>
<path fill="#E5E5E5" d="M60,117.5C28.295,117.5,2.5,91.705,2.5,60S28.295,2.5,60,2.5s57.5,25.795,57.5,57.5S91.705,117.5,60,117.5
z M60,4.075C29.163,4.075,4.075,29.162,4.075,60S29.163,115.925,60,115.925S115.925,90.838,115.925,60S90.837,4.075,60,4.075z"></path>
</g>
</g>
</svg>
If you can't change the id inside each element, you may be able to insert the accessible alternatives with the id once at the start of the page in a display:none element:
<div style="display:none">
<div id="rings-svg">Ring</title>
<div id="rings-svg-desc">An empty circle ring</desc>
</div>
And then insert your SVG in multiple places in your code
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="120px" height="120px" viewBox="0 0 120 120" enable-background="new 0 0 120 120" xml:space="preserve" role="img" aria-labelledby="rings-svg rings-svg-desc" class="rings">
<title>Ring</title>
<desc>An empty circle ring</desc>
<g>
<g>
<path fill="#E5E5E5" d="M60,112.151C31.245,112.151,7.85,88.756,7.85,60C7.85,31.245,31.245,7.851,60,7.851
S112.15,31.245,112.15,60C112.15,88.756,88.755,112.151,60,112.151z M60,9.426C32.113,9.426,9.425,32.113,9.425,60
S32.113,110.576,60,110.576S110.575,87.887,110.575,60S87.887,9.426,60,9.426z"></path>
</g>
<g>
<path fill="#E5E5E5" d="M60,117.5C28.295,117.5,2.5,91.705,2.5,60S28.295,2.5,60,2.5s57.5,25.795,57.5,57.5S91.705,117.5,60,117.5
z M60,4.075C29.163,4.075,4.075,29.162,4.075,60S29.163,115.925,60,115.925S115.925,90.838,115.925,60S90.837,4.075,60,4.075z"></path>
</g>
</g>
</svg>

Adding a link to a single svg path

I'm attempting to add a link to an external webpage on to a single path of an svg. However when i try to use an as you would for a normal link it doesn't work.
Any ideas of how I will be able to achieve this?
HTML Markup - link needed on first path with id="needLink"
<div><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="-119 -263.1 471.1 666.8" style="enable-background:new -119 -263.1 471.1 666.8;" xml:space="preserve">
<style type="text/css">
.ukGreen1{fill:green;}
</style>
<path id="needLink" class="ukGreen1" d="M6.2,312.4c0,0,3.6-0.3,5.6-0.8c2-0.5,13-4.5,13-4.5l6.3-1.4l17.8-4.2c0,0,4-1.1,7.4-0.3
c3.4,0.8,9.4,1.7,12.6-0.2c3.2-1.9,3.9-3.4,6.9-4c0,0,2.5-0.4,3.9-0.9c1.3-0.5,3.7-1,6.3-1.3c1.1-0.1,1.7-0.3,2-0.5l0.3,0.7
c0,0.4,0.1,0.9,0.3,1.4c0.3,1.3-2.3,5.2-4.1,6.5c-1.8,1.3-3.6,6-4.1,7.2c-0.5,1.2-1.7,5.3-1.5,6.1c0.2,0.8-2.9,9.1-2.9,9.1l-4.8,8
l-11.2-2.7l-4.2,1.3l-1.5,0.6L42,336.7l-13.4,7.8l-3,5.4l-0.9-0.5c0,0-0.9-0.2-1.4-2s-2.8-5.8-2.8-5.8c-0.5-2.8-4.2-8-5.5-12.5
s-7.8-10-7.8-10.8s-1.2-5.5-1.2-5.5L6.2,312.4z"/>
<path class="ukGreen1" d="M22.8,354.7l-1.6,14.2l-8,11.6l-10.1-2L-15.3,368l-2.2-3.8l-3.2,3.1l-12-2.2l-22.2,3.7l-12.9,11.7l-9.2,6
l0.3,9.7l-9.4,5.8l-7.4-10.7l-10.3-3.4l-5.1,4.9l-7.5,0.7l0.9-8.8l6.5-5.9l7.3,0.5l8.3-3.5l15.5-16.5l13.5-16.2l21.8-18.3
l2.7-19.6l16.8-5.3l10-17.4l1.3,1.8c0,0,5.5,11.6,6.1,12.8c0.6,1.1,3.9,5,5.6,6c1.6,0.9,3.2,7.4,5.5,9.1l0.7,0.7
c0,0,1.2,4.8,1.2,5.5s6.5,6.2,7.8,10.8s5,9.8,5.5,12.5c0,0,2.2,4,2.8,5.8s1.4,2,1.4,2l0.9,0.5L22.8,354.7z"/>
</svg>
</div>
<svg (...) xmlns:xlink="http://www.w3.org/1999/xlink">
<a xlink:title="title (tooltip) text" xlink:href="http://google.com/">
<whatever drawing markups you want to be linked/>
</a>
In other words: you miss the namespace.

SVG Image dosen't appear in Safari

Well this a label I have on a svg image, it works fine on all browsers except Safari where it will not show up and I can't get why this part of the svg doesn't show up....
<g>
<g>
<defs>
<rect id="SVGID_7_" x="221.463" y="851.163" width="187.789" height="38.692"></rect>
</defs>
<clipPath id="SVGID_8_">
<use xlink:href="#SVGID_7_" overflow="visible"></use>
</clipPath>
<path clip-path="url(#SVGID_8_)" fill="#120F0B" d="M221.463,862.222c0-2.149,1.755-3.904,3.902-3.904h76.462 c2.146,0,5.144-1.242,6.662-2.759l3.254-3.255c1.52-1.52,4.003-1.522,5.522-0.003l3.255,3.258 c1.521,1.517,4.516,2.759,6.665,2.759h78.164c2.146,0,3.902,1.755,3.902,3.904v23.73c0,2.146-1.756,3.903-3.902,3.903H225.365c-2.147,0-3.902-1.757-3.902-3.903V862.222z"/>
</g>
<text transform="matrix(1 0 0 1 277.3213 876.9551)" fill="#FFFFFF" font-family="'FedraSansStd-Normal'" font-size="9.64">Drinkwaterbalans</text>
</g>
and this is the svg tag from the top:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="600px" height="1000px" viewBox="0 0 625 1000"
enable-background="new 0 0 625 1000" xml:space="preserve"
preserveAspectRatio="xMinYMin none">
Found the answer !
if i removed :
<defs>
<rect id="SVGID_7_" x="221.463" y="851.163" width="187.789" height="38.692"></rect></defs>
<clipPath id="SVGID_8_">
<use xlink:href="#SVGID_7_" overflow="visible"></use>
</clipPath>
the grafic shows up even in Safari! and corect
You need to put your SVG declaration before your SVG tag. Add the <g> tag after the <body> tag and put the <svg> tag after the <g> tag.

Resources