0

I'm trying to write a quick blurb of javascript to animate layers from the SVG files generated by Inkscape. Inkscape is nice enough to set the inkscape:groupmode attribute to "layer" for layer groups:

<g
   transform="translate(-12.681101,-9.7947913)"
   id="g2179"
   inkscape:groupmode="layer"
   inkscape:label="Frame 2"
   style="display:inline"
>

So I wrote a little script to find all those nodes, hide them, and then show them one by one in a loop with a delay:

<script type="text/javascript">
    <![CDATA[
        var layers;
        var current = 0;

        // show one at a time
        function animate() {
            if (layers.length > 0) {
                layers[current].style.display = "none";
                current = (current+1) % layers.length;
                layers[current].style.display = "inline";
            }
        }

        // on load, get layers and hide them
        function init() {
            layers = document.querySelectorAll("g[inkscape\\:groupmode='layer']");
            alert(layers.length);

            // hide all layers
            for (var ii=0; ii < layers.length; ii++) {
                layers[ii].style.display = "none";
            }

            setInterval(animate, 500);
        }
    ]]>
  </script>

Where init() is called by onload on the svg element:

<svg onload="init()">

Unfortunately, the querySelectorAll call returns a layers array that's empty (alert shows '0'). I can query all the group elements by removing the attribute identifier, but that's not what I want.

How do I select just the elements that are layers?

Edit: Full example, this pops up "0" in Firefox 71.0, and Chrome 79.0.3945.79 on Linux:

<svg
   onload="init()"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   width="79.63958mm"
   height="79.63958mm"
   viewBox="0 0 79.63958 79.63958">

  <script type="text/javascript">
    <![CDATA[
        var layers;
        var current = 0;

        // show one at a time
        function animate() {
            if (layers.length > 0) {
                layers[current].style.display = "none";
                current = (current+1) % layers.length;
                layers[current].style.display = "inline";
            }
        }

        // on load, get layers and hide them
        function init() {
            layers = document.querySelectorAll("g[inkscape\\:groupmode='layer']");
            alert(layers.length);

            // hide all layers
            for (var ii=0; ii < layers.length; ii++) {
                layers[ii].style.display = "none";
            }

            setInterval(animate, 500);
        }
    ]]>
  </script>

  <g
     inkscape:label="Frame 1"
     inkscape:groupmode="layer"
     id="layer1"
     transform="translate(-12.681101,-9.7947913)"
     style="display:inline">
  </g>
</svg>
6
  • 1
    You are looking for a g element not for a .g class. Change to "g[inkscape\\:groupmode='layer']", or just remove .g. Commented Dec 17, 2019 at 19:39
  • 1
    Good catch, will edit to fix. Unfortunately still not getting elements Commented Dec 17, 2019 at 19:41
  • 1
    Without the class dot it works - jsfiddle.net/d1kh20np Commented Dec 17, 2019 at 19:44
  • Still doesn't work for me in Chrome or Firefox, I updated the question with a full code that's not working. Commented Dec 17, 2019 at 19:54
  • Again, I copied everything, pasted it in a new document (this one) and it alerts 1 in Chrome. Does this at least work for you, if you create a new HTML document and just paste this in it? Commented Dec 17, 2019 at 20:06

1 Answer 1

3

You can't select get element by that type of querySelector, but you can try filtering, the G elements that you need

const g = document.querySelectorAll('g')
const layers = Array.from(g)
    .filter(g => g.getAttribute('inkscape:groupmode') === 'layer')
Sign up to request clarification or add additional context in comments.

2 Comments

That's basically what I just came up with too. Select all, then filter. Any idea why you can't select on the value of that attribute?
HTML doesn't support XML namespaces, in this case inkscape is a namespace.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.