George Profenza
George Profenza

Reputation: 51867

How to traverse an SVG as a tree structure with SnapSVG?

I'm trying SnapSVG and some common tasks are easy to perform with it. However, I can't seem to figure out how to traverse an SVG file as a tree structure. From what I can gather in the documentation select() and selectAll() which either select a single element or collapses groups.

I'm using bunch of groups that look like this:

<g id="FC1">
    <g id="S2B" class="st0">
        <path class="st1" d="M779.838,895.4v43.897h-70.5V895.4H779.838z M709.339,895.4"></path>
        <path class="st1" d="M922.14,895.4h70.5v43.897h-70.5V895.4z M922.14,939.297"></path>
        <path class="st1" d="M567.471,939.297V895.4h70.5v43.897H567.471z M637.97,939.297"></path>
        <path class="st1" d="M993.074,895.4h70.5v43.897h-70.5V895.4z M993.074,939.297"></path>
        <path class="st1" d="M921.706,895.4v43.897h-70.5V895.4H921.706z M851.206,895.4"></path>
        <path class="st1" d="M638.405,895.4h70.5v43.897h-70.5V895.4z M638.405,939.297"></path>
        <path class="st1" d="M1064.008,895.4h70.5v43.897h-70.5V895.4z M1064.008,939.297"></path>
        <path class="st1" d="M780.272,939.297V895.4h70.5v43.897H780.272z M850.772,939.297"></path>
    </g>
    <g id="S2A" class="st0">
        <path class="st1" d="M1418.243,939.297h-70.5V895.4h70.5V939.297z M1418.243,895.4"></path>
        <path class="st1" d="M1489.611,895.4h70.5v43.897h-70.5V895.4z M1489.611,939.297"></path>
        <path class="st1" d="M1418.677,939.297V895.4h70.5v43.897H1418.677z M1489.177,939.297"></path>
        <path class="st1" d="M1205.441,939.297h-70.5V895.4h70.5V939.297z M1205.441,895.4"></path>
        <path class="st1" d="M1560.545,895.4h70.5v43.897h-70.5V895.4z M1560.545,939.297"></path>
        <path class="st1" d="M1347.309,895.4v43.897h-70.5V895.4H1347.309z M1276.809,895.4"></path>
        <path class="st1" d="M1772.912,895.4v43.897h-70.5V895.4H1772.912z M1702.413,895.4"></path>
        <path class="st1" d="M1773.346,895.4h70.5v43.897h-70.5V895.4z M1773.346,939.297"></path>
        <path class="st1" d="M1914.78,939.297h-70.5V895.4h70.5V939.297z M1914.78,895.4"></path>
        <path class="st1" d="M1701.978,939.297h-70.5V895.4h70.5V939.297z M1701.978,895.4"></path>
        <path class="st1" d="M1276.375,939.297h-70.5V895.4h70.5V939.297z M1276.375,895.4"></path>
    </g>
    <g id="S2C" class="st0">
        <path class="st1" d="M283.735,939.297V895.4h70.5v43.897H283.735z M354.235,939.297"></path>
        <path class="st1" d="M496.537,939.297V895.4h70.5v43.897H496.537z M567.037,939.297"></path>
        <path class="st1" d="M425.169,939.297h-70.5V895.4h70.5V939.297z M425.169,895.4"></path>
        <path class="st1" d="M496.103,939.297h-70.499V895.4h70.499V939.297z M496.103,895.4"></path>
    </g>
</g>

If I do select("g) this hierarchy is collapsed.

I can use plain JS and document.querySelector() to access elements, but I was hoping to use some of SnapSVG's features.

What is the recommended way to traverse a tree hierarchy with SnapSVG ?

Upvotes: 0

Views: 590

Answers (1)

Ian
Ian

Reputation: 13852

selectAll() with a forEach() would be my normal way...you can combine them as well,

So Snap('#FC1') or Snap('g') selects the first g element or you can use paper.select('#FC1') if you already have an svg/group element. You can then use select/selectAll on that element (as long as its a container element like g/svg).

You can combine, for example...

paper.select('g').selectAll('g').forEach( doSomethingFunc ) 

This would select the first g element, and then select all of the g elements inside the first g element.

When you use Snap( selector ) or selectAll type thing, behind the scenes its using a css querySelectorAll, so you can think of them similar.

For example, if you had several nested 'g's, you could use a css selector to specify the first level, parse through that, and act on them...eg

var gs3 = s.selectAll('svg>g').forEach ( selectNext )

function selectNext( el ) {
  var els = el.selectAll('g>g'); // do children
  console.log( els )
}

jsfiddle

Or if you want, you can access the DOM directly, with something like

el.node.children

And reference them, you can alwaya 'Snapify' them to use Snap again with Snap(DOMelement) as you loop through them.

Upvotes: 1

Related Questions