I'd like to manipulate the internal path of a SVG which is in a separate file and instantiated with a "use"
here is my code
<!DOCTYPE html><meta charset="utf8"/>
<script src="https://ipfs.blockringtm.ml/ipfs/QmZU12UqysToVJjNmWo3E31i4tmmMbWyxZ82Vyse9CQp49/path-data-polyfill.js"></script>
<svg data="logo.svg" type="image/svg+xml" id="logo"
width="120px"
preserveAspectRatio="xMidYMin slice" viewBox="0 0 512 512"
>
<!-- https://stackoverflow.com/questions/65526455/trying-to-access-svg-elements-generated-with-use-with-javascript -->
<!--
SVG use elements are like shadow DOM elements in HTML. Only the attributes
of the USE element itself is exposed via the SVG DOM - you cannot alter
any properties on a single USE element instance that are being cloned
from the original symbol. It's not like a macro.
-->
<use id="logo1" xlink:href="logo.svg#logo"></use>
</svg>
<script>
var svg = document.querySelector('#logo');
var use = svg.querySelector('#logo1');
console.log('use:',use);
var paths = use.querySelectorAll('path'); // FAILED HERE : empty NodeList: []
console.log('paths:',paths);
for (let path of paths) {
var pathdata = path.getPathData();
console.log(pathdata);
}
</script>
The svg file is :
<svg id="logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 196.1 236.8">
<defs>
<linearGradient id="a">
<stop offset="0" stop-color="#606"/>
<stop offset="1"/>
</linearGradient>
</defs>
<path id="pin" fill="#01a49b" d="M30.3 168a94.8 94.8 0 0063.2 27.2 95 95 0 0065.6-21.8c.8-.8 17.6-16 1.2.6l-28 28.2L98 236.8l-68.1-68c-6.5-6.5-12.6-15.5-12.6-15.5a88.1 88.1 0 0013 14.7z"/>
<path if="wrench" fill="#660266" d="M13.5 47.8C36.2 8.5 97-15.8 145 11.9c41.1 23.7 69.1 81.4 37.6 135-17.6 30-49.3 44-65 46.7-4 .7-18.3 1.9-22.5 1.9-1.3-.1-1.8-1.2-1-2.6l17.5-30.8c14.7-4.5 32-11.3 44.2-32.4a66.7 66.7 0 00-26.5-90.8C93.8 18.7 55 37.9 40 63.7A64.5 64.5 0 0051 144l8.2-14.5c2.2-3.8 2.4-4.5-.2-9A46.6 46.6 0 0158 73.3a44.8 44.8 0 0134.5-21.7c5.4-.3 4.8 1 3.7 2.7L80 82.3l9.4 16.3c1.7 3 5 6 8.5 5.9l22-2 15.3-26c1.3-1.9 2.2 0 3 2.2.7 2.2 10.4 16.9-2.5 39.3a45.3 45.3 0 01-37.9 23.4c-4.8-.3-6.1 2.5-8.7 7L65 190A99.7 99.7 0 012.7 121c-6.4-25.7-.8-53.3 10.8-73.3z"/>
</svg>
if I use an <object>
tag instead of the <use>
I can access the internal path with a path.pathSegList
however it doesn't work with path.getPathData pollyfill as the path is a plain object and not a SVGPathElement.
Questions :
- how to I get a SVGPathElement from a path within an Object tag ? i.e. how to I cast a DOMobject into a SVGPathElement ?
- alternatively is there a way to I get and "open" shadow-root with the use tag, do I need to create the tag within the script to keep it open ?
The code (that works) with the object tag instance is :
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, initial-scale=1.0" charset="utf8">
<script src="http://ipfs.blockringtm.ml/ipfs/QmU3jKAewrHV8Wryx2WzT5v72PsgT7wt8FgnL8mqmWk259/path-data-polyfill.js"></script>
<style>
body { border:0; margin:0; padding: 0; height: 100vh; top: 0; }
svg { border: 1px dashed #555 }
</style>
<object id="sotest1" style="width:100px" data="logo.svg" type="image/svg+xml"></object>
<script>
let obj = document.querySelector('#sotest1');
obj.addEventListener("load",function(){
console.log('obj.loaded !');
var svgDoc = obj.contentDocument;
console.log('svgDoc:',svgDoc);
let path1 = svgDoc.querySelector("#pin");
console.log('typeof:',typeof(path1))
console.log('#path.d:',path1.getAttribute('d'));
let paths = svgDoc.getElementsByTagName('path');
for (let p of paths) {
let d = p.getAttribute('d'); // does work but can get p.getPathData() to work
console.log('p.d:',d);
}
},false);
</script>
if you want to get the file I have prepared a gist for it : https://gist.github.com/DrI-T/145db3eed5905f83333d8127cbf2c6b8