S.Dan
S.Dan

Reputation: 1930

How to implement collapsible tree structure using svg g

I implemented a tree structure using svg g components - the reason for using svg is a long story that involves draggable nodes.

The following hides and displays when the parent node is clicked but it is not the same as collapsing. What will be the best approach to correctly implement collapsible/expandable functionality (when children are hidden, the lower siblings positions must come up etc.)

Should I iterates through the siblings and update their positions or is there a simpler way?

The tree structure - branches - and expand/collapse icons are to be added later.

d3.selectAll(".nested-group").each(function() {
  var sib = d3.select(this).select(".nested-group");
  d3.select(this).select(".parent-node").on("click", function() {

    sib.style("display", function() {
      return (sib.style("display") === "none" ? "inline" : "none");
    });

  })
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg class="canvas" width="1800" height="500">
  <g id="input-container" transform="translate(0,0)">

    <g id="input-container-fo" class="container-fo">
      <rect width="317.5" y="20" x="40" class="container-title-outline" id="input-container-title-outline" height="20" fill="#77C1C0" stroke="black"></rect>
      <text width="270" y="35" x="40" class="container-title" id="input-container-title" font-weight="bold">Input</text>
      <rect stroke-width="1" width="317.5" y="20" x="40" class="container-outline" id="input-container-outline" height="360" fill="none" stroke="black"></rect>
    </g>
    <g class="nested-group">
      <g width="170" height="20" class="node-element parent-node">
        <text y="55" x="51" class="node-element-text">person:object</text>
      </g>
      <g class="nested-group">
        <g>
          <g width="170" height="20" class="node-element leaf-node">
            <text y="75" x="93.5" class="node-element-text">first name:string</text>

          </g>
        </g>
        <g>
          <g width="170" height="20" class="node-element leaf-node">
            <text y="95" x="93.5" class="node-element-text">last name:string</text>

          </g>
        </g>
        <g>
          <g width="170" height="20" class="node-element leaf-node">
            <text y="115" x="93.5" class="node-element-text">age:number</text>

          </g>
        </g>
        <g>
          <g width="170" height="20" class="node-element leaf-node">
            <text y="135" x="93.5" class="node-element-text">birthday:string</text>

          </g>
        </g>
        <g class="nested-group">
          <g width="170" height="20" class="node-element parent-node">
            <text y="155" x="93.5" class="node-element-text">address:object</text>
          </g>
          <g class="nested-group">
            <g class="nested-group">
              <g width="170" height="20" class="node-element parent-node">
                <text y="175" x="136" class="node-element-text">street address:object</text>
              </g>
              <g class="nested-group">
                <g>
                  <g width="170" height="20" class="node-element leaf-node">
                    <text y="195" x="178.5" class="node-element-text">house number:number</text>

                  </g>
                </g>
                <g>
                  <g width="170" height="20" class="node-element leaf-node">
                    <text y="215" x="178.5" class="node-element-text">lane:string</text>

                  </g>
                </g>
              </g>
            </g>
            <g>
              <g width="170" height="20" class="node-element leaf-node">
                <text y="235" x="136" class="node-element-text">city:string</text>

              </g>
            </g>
            <g>
              <g width="170" height="20" class="node-element leaf-node">
                <text y="255" x="136" class="node-element-text">state:string</text>

              </g>
            </g>
            <g>
              <g width="170" height="20" class="node-element leaf-node">
                <text y="275" x="136" class="node-element-text">country:string</text>

              </g>
            </g>
          </g>
        </g>
        <g class="nested-group">
          <g width="170" height="20" class="node-element parent-node">
            <text y="295" x="93.5" class="node-element-text">phone number:array[object]</text>
          </g>
          <g class="nested-group">
            <g class="nested-group">
              <g>
                <g width="170" height="20" class="node-element leaf-node">
                  <text y="315" x="136" class="node-element-text">location:string</text>

                </g>
              </g>
              <g>
                <g width="170" height="20" class="node-element leaf-node">
                  <text y="335" x="136" class="node-element-text">code:number</text>
                
                </g>
              </g>
            </g>
          </g>
        </g>
        <g class="nested-group">
          <g width="170" height="20" class="node-element parent-node">
            <text y="355" x="93.5" class="node-element-text">children:array[string]</text>
          </g>
          <g></g>
        </g>
        <g>
          <g width="170" height="20" class="node-element leaf-node">
            <text y="375" x="93.5" class="node-element-text">nickname:string</text>
            
          </g>
        </g>
      </g>
    </g>
  </g>




</svg>

Upvotes: 2

Views: 1178

Answers (1)

Paul LeBeau
Paul LeBeau

Reputation: 101938

There is no automatic layout in SVG like there is in HTML. So there is no way for the position of later elements to automatically adjust when another element is shown or hidden.

So, to answer your question, yes, you will have to adjust the positions of other elements yourself.

Upvotes: 3

Related Questions