CedGrvl Posted November 1, 2019 Posted November 1, 2019 I have a site with several svg icons and svg logo that I have to animate. For a better readability, I use a sprite system on an external file. I use XMLHttpRequests to load sprites at the beginning of the request. function getSprites(url){ var ajax = new XMLHttpRequest(); ajax.open("GET", url, true); ajax.send(); ajax.onload = function() { var div = document.createElement("div"); div.innerHTML = ajax.responseText; document.body.insertBefore(div, document.body.childNodes[0]); } } getSprites("./assets/images/sprites-icon.svg"); getSprites("./assets/images/sprites-logo.svg"); as soon as I use queryselector to select an element and animate it, this one is undefined for example let shapeLogoRoadmap = document.querySelector('.js-shape-roadmap-logo').childNodes; and here an example of svg symbol from sprite <symbol id="roadmap-small-logo" viewBox="0 0 250 250"> <g class="js-shape-roadmap-logo"> <path fill="#93718d" style="fill: var(--first-color, #93718d)" filter="url(#AI_Shadow_2)" d="M219.4366,111.5074l-80.944-80.944a19.1431,19.1431,0,0,0-26.9852,0l-80.944,80.944a19.1431,19.1431,0,0,0,0,26.9852l80.944,80.944a19.1431,19.1431,0,0,0,26.9852,0l80.944-80.944A19.1431,19.1431,0,0,0,219.4366,111.5074ZM200.5485,135.791,135.791,200.5485a15.3013,15.3013,0,0,1-21.582,0L49.4515,135.791a15.3013,15.3013,0,0,1,0-21.582L114.209,49.4515a15.3013,15.3013,0,0,1,21.582,0l64.7575,64.7575A15.3013,15.3013,0,0,1,200.5485,135.791Z"/> <path fill="#977792" style="fill: var(--second-color, #977792)" filter="url(#AI_Shadow_2)" d="M201.15,114.1231,135.8769,48.85a15.4233,15.4233,0,0,0-21.7538,0L48.85,114.1231a15.4233,15.4233,0,0,0,0,21.7538L114.1231,201.15a15.4233,15.4233,0,0,0,21.7538,0L201.15,135.8769A15.4233,15.4233,0,0,0,201.15,114.1231Zm-15.2308,19.5807-52.2154,52.2154a12.3428,12.3428,0,0,1-17.4077,0L64.0808,133.7038a12.3428,12.3428,0,0,1,0-17.4077l52.2153-52.2153a12.3428,12.3428,0,0,1,17.4077,0l52.2154,52.2153A12.3428,12.3428,0,0,1,185.9192,133.7038Z"/> <path fill="#9c7d96" style="fill: var(--third-color, #9c7d96)" filter="url(#AI_Shadow_2)" d="M185.9192,116.2961,133.7038,64.0808a12.3428,12.3428,0,0,0-17.4077,0L64.0808,116.2961a12.3428,12.3428,0,0,0,0,17.4077l52.2153,52.2154a12.3428,12.3428,0,0,0,17.4077,0l52.2154-52.2154A12.3428,12.3428,0,0,0,185.9192,116.2961Zm-12.1846,15.6654-41.7731,41.7731a9.87,9.87,0,0,1-13.923,0L76.2654,131.9615a9.87,9.87,0,0,1,0-13.923l41.7731-41.7731a9.87,9.87,0,0,1,13.923,0l41.7731,41.7731A9.87,9.87,0,0,1,173.7346,131.9615Z"/> <path fill="#a0829b" style="fill: var(--fourth-color, #a0829b)" filter="url(#AI_Shadow_2)" d="M173.7346,118.0385,131.9615,76.2654a9.87,9.87,0,0,0-13.923,0L76.2654,118.0385a9.87,9.87,0,0,0,0,13.923l41.7731,41.7731a9.87,9.87,0,0,0,13.923,0l41.7731-41.7731A9.87,9.87,0,0,0,173.7346,118.0385Zm-9.7461,12.5307-33.4193,33.4193a7.8951,7.8951,0,0,1-11.1384,0L86.0115,130.5692a7.8951,7.8951,0,0,1,0-11.1384l33.4193-33.4193a7.8949,7.8949,0,0,1,11.1384,0l33.4193,33.4193A7.8951,7.8951,0,0,1,163.9885,130.5692Z"/> <path fill="#a98ea4" style="fill: var(--fifth-color, #a98ea4)" filter="url(#AI_Shadow_2)" d="M163.9885,130.5692l-33.4193,33.4193a7.8951,7.8951,0,0,1-11.1384,0L86.0115,130.5692a7.8951,7.8951,0,0,1,0-11.1384l33.4193-33.4193a7.8949,7.8949,0,0,1,11.1384,0l33.4193,33.4193A7.8951,7.8951,0,0,1,163.9885,130.5692Z"/> </g> </symbol> I tried setinterval on animation but without success In this situation, I want to have access to each path because I animate them one after the other. Should I give them the same class name? or? svg are as clear as possible, but I prefer to avoid inline svg but if there is no other better solution.... I need to have access to each path of the svg I read that you can have problems with childnodes in this kind of situation? If I understood correctly from the moment I want to access the "nodes" I have a problem with the shadow DOM? To summarize, I would like to be able to manage each path of my svg, keeping a good organization. I asked this question also on stack owerflow Sorry about the copy/past Thx Guys !
ZachSaucier Posted November 1, 2019 Posted November 1, 2019 Hey CedGrvl, In theory document.querySelector('.js-shape-roadmap-logo') should return your element after the content has been loaded. This sort of thing is best if you put it in a minimal demo so we can see exactly what's going on. The thread below can help you set up a minimal demo:
CedGrvl Posted November 1, 2019 Author Posted November 1, 2019 See the Pen QWWabVJ by tanikimura-the-animator (@tanikimura-the-animator) on CodePen. Finaly nothing to see with XMLHttpRequest. It's an issue with the shadow DOM I guess
ZachSaucier Posted November 1, 2019 Posted November 1, 2019 You didn't have the class anywhere in the HTML... It works fine: See the Pen OJJzyWr?editors=0010 by GreenSock (@GreenSock) on CodePen. 1
CedGrvl Posted November 2, 2019 Author Posted November 2, 2019 I should read myself more for sure. So the issue comes from XMLHttpRequest Sometimes it works when I refresh the page multiple time ?
ZachSaucier Posted November 4, 2019 Posted November 4, 2019 On 11/2/2019 at 4:04 PM, CedGrvl said: Sometimes it works when I refresh the page multiple time ? Sounds like it's a race condition then. Your listener should be on the completion of it, not a random time after it is initialized. If you can recreate your situation in a demo, we'd be happy to give it a look!
CedGrvl Posted November 5, 2019 Author Posted November 5, 2019 Thx Zach I'll give you a pen asap. I put my sprites inline for now !
OSUblake Posted November 5, 2019 Posted November 5, 2019 Very easy way to load svgs. Look at the js files. See the Pen 8d6d379841ed3b5c6f20b10dc19e4b95 by osublake (@osublake) on CodePen. 4
CedGrvl Posted November 6, 2019 Author Posted November 6, 2019 Oh Great Is it possible to understand what I did wrong ? See the Pen NWWYoEv by CedGrvl (@CedGrvl) on CodePen. I found this solution here https://css-tricks.com/ajaxing-svg-sprite/ after I saw one of your posts, I think Blake. So if I understand correctly, you're using a window object? and there are two ways to inject? innerHTML or insertAdjacentHTML ? First time I see the inverted quote very useful Feel so far from being confortable with js Thx
OSUblake Posted November 6, 2019 Posted November 6, 2019 3 hours ago, CedGrvl said: Oh Great Is it possible to understand what I did wrong ? You have to wait for it to load before selecting an element. And your your SVG doesn't have a .js-shape-roadmap-logo element. Perhaps you changed it. var ajax = new XMLHttpRequest(); ajax.open("GET", "https://codepen.io/CedGrvl/pen/ZEExVjL.html", true); ajax.send(); ajax.onload = function(e) { var div = document.createElement("div"); div.innerHTML = ajax.responseText; document.body.insertBefore(div, document.body.childNodes[0]); // let shapeLogoRoadmap = document.querySelector('.js-shape-roadmap-logo').childNodes; let shapeLogoRoadmap = document.querySelector('#roadmap-big-logo').childNodes; console.log(shapeLogoRoadmap); } I'll just add that animating <use> elements can be annoying because you can't select child nodes. You're actually selecting the symbol in the svg you loaded. Changing that symbol affects all <use> elements that link to it. 3 hours ago, CedGrvl said: I found this solution here https://css-tricks.com/ajaxing-svg-sprite/ after I saw one of your posts, I think Blake. There are several ways to load SVGs. Here's a more modern way using promises and fetch instead of callbacks and ajax. See the Pen 27ecfcb76a799484b07a1d6ef75ba6b3 by osublake (@osublake) on CodePen. 3 hours ago, CedGrvl said: and there are two ways to inject? innerHTML or insertAdjacentHTML ? For strings, yes. innerHTML replaces everything inside an element. insertAdjacentHTML doesn't replace anything. You can choose from 4 different positions to append/prepend the html to. https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML 3 hours ago, CedGrvl said: First time I see the inverted quote very useful There's a lot of neat uses for that. https://css-tricks.com/template-literals/ 4
OSUblake Posted November 6, 2019 Posted November 6, 2019 3 hours ago, CedGrvl said: So if I understand correctly, you're using a window object? Forgot to mention, that yes, I'm using the window to make it global. This pattern makes sure it doesn't overwrite window.mySvg if it already exists. window.mySvg = window.mySvg || {}; 3
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now