CedGrvl Posted November 1, 2019 Share 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 ! Link to comment Share on other sites More sharing options...
ZachSaucier Posted November 1, 2019 Share 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: Link to comment Share on other sites More sharing options...
CedGrvl Posted November 1, 2019 Author Share 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 Link to comment Share on other sites More sharing options...
ZachSaucier Posted November 1, 2019 Share 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 Link to comment Share on other sites More sharing options...
CedGrvl Posted November 2, 2019 Author Share 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 ? Link to comment Share on other sites More sharing options...
ZachSaucier Posted November 4, 2019 Share 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! Link to comment Share on other sites More sharing options...
CedGrvl Posted November 5, 2019 Author Share Posted November 5, 2019 Thx Zach I'll give you a pen asap. I put my sprites inline for now ! Link to comment Share on other sites More sharing options...
OSUblake Posted November 5, 2019 Share 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 Link to comment Share on other sites More sharing options...
CedGrvl Posted November 6, 2019 Author Share 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 Link to comment Share on other sites More sharing options...
OSUblake Posted November 6, 2019 Share 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 Link to comment Share on other sites More sharing options...
CedGrvl Posted November 6, 2019 Author Share Posted November 6, 2019 Thank you for these explanations Link to comment Share on other sites More sharing options...
OSUblake Posted November 6, 2019 Share 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 Link to comment Share on other sites More sharing options...
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