# Getting layers to work with SVG

**URL:** <https://forum.graphviz.org/t/getting-layers-to-work-with-svg/107>\
**Category:** Show and Tell\
**Created:** [May 17, 2020, 9:28pm UTC](https://forum.graphviz.org/t/getting-layers-to-work-with-svg/107 "2020-05-17T21:28:24Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![steveroush](https://avatars.discourse-cdn.com/v4/letter/s/a9adbd/32.png) [@steveroush](https://forum.graphviz.org/u/steveroush)\
**Post date:** [May 17, 2020, 9:28pm UTC](https://forum.graphviz.org/t/getting-layers-to-work-with-svg/107/1 "2020-05-17T21:28:24Z")

</div>

At a high level, **layers** allows you to define a set of graphs where node and edge positioning stays constant but individual nodes and edges may not be visible in any graph within the set. (whew, the Graphviz documentation explains this better)  
While Graphviz’s SVG output supports **layers** as best it can, SVG only shows you the “first” graph/layer (think of it as the graph on the top page of a stack of pages).  
I’ve dusted off some **javascript** that _in theory_ can be added to any SVG output file that contains **layers** to add the ability to see each layer, one-at-a-time.  
Three examples:  
[https://cdn.statically.io/gist/steveroush/23478aefac88d1f15e10529202ff4832/raw/58d980330904c46cb71a016f5ab6819c8970e3da/Layer3.svg](https://cdn.statically.io/gist/steveroush/23478aefac88d1f15e10529202ff4832/raw/58d980330904c46cb71a016f5ab6819c8970e3da/Layer3.svg)  
[https://cdn.statically.io/gist/steveroush/aedb1c04acddc1311b2d8d4bd72d4e46/raw/e4e08dca72b0cc4a1e5d7414c69d051f761572e1/unixLayers.svg](https://cdn.statically.io/gist/steveroush/aedb1c04acddc1311b2d8d4bd72d4e46/raw/e4e08dca72b0cc4a1e5d7414c69d051f761572e1/unixLayers.svg)  
[https://cdn.statically.io/gist/steveroush/3ca7a088b8bc08eb6ab09e6d10e7d36d/raw/ba5491b66dcd0b7bda15d0c63e61dd42b5d9b482/SLshow.svg](https://cdn.statically.io/gist/steveroush/3ca7a088b8bc08eb6ab09e6d10e7d36d/raw/ba5491b66dcd0b7bda15d0c63e61dd42b5d9b482/SLshow.svg)

Questions:

- Does anybody care?

- Is there a better user interface

- What features are missing?

My javascript skill is mediocre (at best) and antiquated, so improvements are appreciated.

---

<div class="post-metadata">

**Author:** ![magjac](https://sea2.discourse-cdn.com/graphviz/user_avatar/forum.graphviz.org/magjac/32/16_2.png) [@magjac](https://forum.graphviz.org/u/magjac)\
**Post date:** [May 17, 2020, 10:22pm UTC](https://forum.graphviz.org/t/getting-layers-to-work-with-svg/107/2 "2020-05-17T22:22:34Z")

</div>

Q1: yes  
Q2: yes, buttons to play, pause, stop, forward, backward, repeat etc and a slider for speed.  
Q3: If you provide the DOT source code, I can give you a hint on what [d3-graphviz](https://github.com/magjac/d3-graphviz) could provide.

Do you have a preference for _how_ this should be used?

1. As it is now, i.e. serve a self-contained application embedded in the SVG from somewhere. This means the user must prepare the SVG offline (inlcuding embedding the JavaScript) and upload it somewhere and then link to it from somewhere else.
2. A stand-alone web application where the user supplies the DOT source code and gets this new functionality. This could be built into the [Graphviz Visual Editor](http://magjac.com/graphviz-visual-editor).
3. A library where the user can supply the DOT source code and gets the SVG rendered and some support functions to easily produce this new functionality, but add their own user interface and build their web own application? This could be built in to [d3-graphviz](https://github.com/magjac/d3-graphviz).
4. Directly generate the animated transition from the DOT source code in a post here on the forum. This could be built into the [D3 Graphviz Discourse Theme Component](https://github.com/magjac/discourse-d3-graphviz) that I’m currently developing.
5. Something completely different.

I guess I’m asking what your ultimate use case is.

---

<div class="post-metadata">

**Author:** ![steveroush](https://avatars.discourse-cdn.com/v4/letter/s/a9adbd/32.png) [@steveroush](https://forum.graphviz.org/u/steveroush)\
**Post date:** [May 18, 2020, 12:11am UTC](https://forum.graphviz.org/t/getting-layers-to-work-with-svg/107/3 "2020-05-18T00:11:36Z")

</div>

I like buttons & sliders, but they are kind of a pain in SVG. However if embedding the SVG inside HTML is OK, then those controls are easy.

One ultimate use case is adding an improved version of the javascript to Graphviz’s SVG generator _gvrender\_core\_svg.c_ as an option or default whenever the input included layers.

Here is the javascript (blush) - just add it to the SVG output just before the last line:

```
<script type="text/javascript" >
<![CDATA[ 
                                               	
  var forward=1;
   var backward=-1;
   var intervalMilliseconds=0;       					
   var timer;       					
   var currId=-1; 
   var oldId;      					
   var layer = new Array();   

   window.addEventListener("load", function() {
     //alert("loaded");
     initialize();
     showHelp();
   });

  document.onkeydown = function(e) {
    switch (e.keyCode) {
        case 37:
            direction=backward;
            break;
        case 38:
            intervalMilliseconds-=1000;
            changeSpeed();
            break;
        case 39:
            direction=forward;
            break;
        case 40:
            intervalMilliseconds+=1000;
            changeSpeed();
            break;
        default:
            showHelp();
            break;
    }
  };

   function showHelp(){
     //alert('up arrow: \tfaster\ndown arrow:\tslower\nleft arrow:\tbackward\nright arrow:\tforward');
     alert('left arrow:\tbackward\nright arrow:\tforward\nup arrow: \tfaster\ndown arrow:\tslower');
   }

   function initialize(){                            	
     // copy the "live" nodelist into a real array 
     var layerList = document.getElementsByClassName('layer');
     for (var i =0;i<layerList.length;i++){
       layer.push(layerList[i]);
     }
     // make all layers invisible, except the 1st
     for (var i=1;i<layer.length;i++){ 	                        
       target=layer[i]; 
       target.setAttribute("display", "none");
     }                                                      

     currId=0;
     intervalSeconds=4;
     direction=forward;
     intervalMilliseconds=intervalSeconds*1000;        
     timer=setInterval("show()",intervalMilliseconds);     
   }                                                      
      	                                                        
   function changeSpeed(){
     clearInterval(timer);
     timer=setInterval("show()",intervalMilliseconds);     
   }
   function show(){
 
     oldId=currId;                                                      
     if (direction==forward){	                                        
       if (currId==layer.length - 1) {                           
         //currId=0; 
         clearInterval(timer);
         return;                                          
       }else{                                                     
         currId++;                                              
       }
     } else if (direction==backward){                                 
       if (currId==0){                                           
         //currId=layer.length - 1;                              
         clearInterval(timer);
         return;                                          
       }else{                                           
         currId--;                                              
       }
     }
     // make previous layer invisible
     if (oldId>=0){ 	                                        
       target=layer[oldId];	       
       target.setAttribute("display", "none");          
     }
     // make this layer visible                             
     target=layer[currId];    		
     target.setAttribute("display", "inline");    		
   }	                     
  
  ]]>
</script>
```

---

<div class="post-metadata">

**Author:** ![magjac](https://sea2.discourse-cdn.com/graphviz/user_avatar/forum.graphviz.org/magjac/32/16_2.png) [@magjac](https://forum.graphviz.org/u/magjac)\
**Post date:** [May 18, 2020, 1:50am UTC](https://forum.graphviz.org/t/getting-layers-to-work-with-svg/107/4 "2020-05-18T01:50:47Z")

</div>

I already have the JavaScript (extracted from your SVGs). I wanted the DOT source code for your three examples.

---

<div class="post-metadata">

**Author:** ![steveroush](https://avatars.discourse-cdn.com/v4/letter/s/a9adbd/32.png) [@steveroush](https://forum.graphviz.org/u/steveroush)\
**Post date:** [May 18, 2020, 2:40am UTC](https://forum.graphviz.org/t/getting-layers-to-work-with-svg/107/5 "2020-05-18T02:40:35Z")

</div>

Here they are:  
[https://gist.github.com/steveroush/fbf005465cd8d30e2f6488ff7e248e3e](https://gist.github.com/steveroush/fbf005465cd8d30e2f6488ff7e248e3e)

[https://gist.github.com/steveroush/4458de9beac9a3be8af424316bf7930e](https://gist.github.com/steveroush/4458de9beac9a3be8af424316bf7930e)

[https://gist.github.com/steveroush/686ac93dd5708f11252b498faf204f5e](https://gist.github.com/steveroush/686ac93dd5708f11252b498faf204f5e)

---

<div class="post-metadata">

**Author:** ![magjac](https://sea2.discourse-cdn.com/graphviz/user_avatar/forum.graphviz.org/magjac/32/16_2.png) [@magjac](https://forum.graphviz.org/u/magjac)\
**Post date:** [May 18, 2020, 10:20pm UTC](https://forum.graphviz.org/t/getting-layers-to-work-with-svg/107/6 "2020-05-18T22:20:29Z")

</div>

_If_ [d3-graphviz](https://github.com/magjac/d3-graphviz) supported layers, ~~this is what you would get~~. **EDIT:** No, you wouldn’t. The next reply shows that.

The extra features are:

- Smooth animated transitions between the layers.
- Fade-in and fade-out of entering and exiting components
- Growing edges (when they are new in a layer)
- Pan & zoom
- Play, pause, stop & repeat button. Those are specific to this forum and not built into d3-graphviz.

[dot verbose=true width=600 height=200]

```auto
digraph G {
#	layers="local:pvt:test:new:ofc";
        node [style=filled,color=lightblue];
#	node1 [layer="pvt"];
	node2 [layer="all",color=red];
#	node3 [layer="pvt:ofc"]; /* pvt, test, new, and ofc */
#	node2 -> node3 [layer="pvt:all"];	/* same as pvt:ofc */
#	node2 -> node4 [layer=3]; /* same as test */
}

```

[/dot]  
[dot verbose=true]

```auto
digraph G {
#	layers="local:pvt:test:new:ofc";
        node [style=filled,color=lightblue];
	node1 [layer="pvt"];
	node2 [layer="all",color=red];
	node3 [layer="pvt:ofc"]; /* pvt, test, new, and ofc */
	node2 -> node3 [layer="pvt:all"];	/* same as pvt:ofc */
#	node2 -> node4 [layer=3]; /* same as test */
}

```

[/dot]  
[dot verbose=true]

```auto
digraph G {
#	layers="local:pvt:test:new:ofc";
        node [style=filled,color=lightblue];
#	node1 [layer="pvt"];
	node2 [layer="all",color=red];
	node3 [layer="pvt:ofc"]; /* pvt, test, new, and ofc */
	node2 -> node3 [layer="pvt:all"];	/* same as pvt:ofc */
	node2 -> node4 [layer=3]; /* same as test */
}

```

[/dot]  
[dot verbose=true]

```auto
digraph G {
#	layers="local:pvt:test:new:ofc";
        node [style=filled,color=lightblue];
#	node1 [layer="pvt"];
	node2 [layer="all",color=red];
  	node3 [layer="pvt:ofc"]; /* pvt, test, new, and ofc */
	node2 -> node3 [layer="pvt:all"];	/* same as pvt:ofc */
#	node2 -> node4 [layer=3]; /* same as test */
}

```

[/dot]  
[dot verbose=true]

```auto
digraph G {
#	layers="local:pvt:test:new:ofc";
        node [style=filled,color=lightblue];
#	node1 [layer="pvt"];
	node2 [layer="all",color=red];
	node3 [layer="pvt:ofc"]; /* pvt, test, new, and ofc */
	node2 -> node3 [layer="pvt:all"];	/* same as pvt:ofc */
#	node2 -> node4 [layer=3]; /* same as test */
}

```

[/dot]

As you can see, I’ve cheated by commenting out components that are not visible in a layer. The idea is just to show what you would get if layers were supported.

---

<div class="post-metadata">

**Author:** ![magjac](https://sea2.discourse-cdn.com/graphviz/user_avatar/forum.graphviz.org/magjac/32/16_2.png) [@magjac](https://forum.graphviz.org/u/magjac)\
**Post date:** [May 19, 2020, 12:03pm UTC](https://forum.graphviz.org/t/getting-layers-to-work-with-svg/107/7 "2020-05-19T12:03:51Z")

</div>

Although the above was kind of funny, it wasn’t at all like your true layered version. Here is one that is:

[dot verbose=true width=600 height=200]

```auto
digraph G {
# layers="local:pvt:test:new:ofc";
        node [style=filled,color=lightblue];
        node1 [layer="pvt" style=invis];
        node2 [layer="all",color=red];
        node3 [layer="pvt:ofc" style=invis]; /* pvt, test, new, and ofc */
        node2 -> node3 [layer="pvt:all" style=invis]; /* same as pvt:ofc */
        node2 -> node4 [layer=3 style=invis]; /* same as test */
        node4 [layer=3 style=invis]; /* same as test */
}

```

[/dot]  
[dot verbose=true]

```auto
digraph G {
# layers="local:pvt:test:new:ofc";
        node [style=filled,color=lightblue];
        node1 [layer="pvt"];
        node2 [layer="all",color=red];
        node3 [layer="pvt:ofc"]; /* pvt, test, new, and ofc */
        node2 -> node3 [layer="pvt:all"]; /* same as pvt:ofc */
        node2 -> node4 [layer=3 style=invis]; /* same as test */
        node4 [layer=3 style=invis]; /* same as test */
}

```

[/dot]  
[dot verbose=true]

```auto
digraph G {
# layers="local:pvt:test:new:ofc";
        node [style=filled,color=lightblue];
        node1 [layer="pvt" style=invis];
        node2 [layer="all",color=red];
        node3 [layer="pvt:ofc"]; /* pvt, test, new, and ofc */
        node2 -> node3 [layer="pvt:all"]; /* same as pvt:ofc */
        node2 -> node4 [layer=3]; /* same as test */
}

```

[/dot]  
[dot verbose=true]

```auto
digraph G {
# layers="local:pvt:test:new:ofc";
        node [style=filled,color=lightblue];
        node1 [layer="pvt" style=invis];
        node2 [layer="all",color=red];
        node3 [layer="pvt:ofc"]; /* pvt, test, new, and ofc */
        node2 -> node3 [layer="pvt:all"]; /* same as pvt:ofc */
        node2 -> node4 [layer=3 style=invis]; /* same as test */
        node4 [layer=3 style=invis]; /* same as test */
}

```

[/dot]  
[dot verbose=true]

```auto
digraph G {
# layers="local:pvt:test:new:ofc";
        node [style=filled,color=lightblue];
        node1 [layer="pvt" style=invis];
        node2 [layer="all",color=red];
        node3 [layer="pvt:ofc"]; /* pvt, test, new, and ofc */
        node2 -> node3 [layer="pvt:all"]; /* same as pvt:ofc */
        node2 -> node4 [layer=3, style=invis]; /* same as test */
        node4 [layer=3 style=invis]; /* same as test */
}

```

[/dot]

Instead of commenting out components that are not visible in a layer, I’ve made in them… guess what? (a brilliant idea 🤣) … invisible.

---

<div class="post-metadata">

**Author:** ![magjac](https://sea2.discourse-cdn.com/graphviz/user_avatar/forum.graphviz.org/magjac/32/16_2.png) [@magjac](https://forum.graphviz.org/u/magjac)\
**Post date:** [May 22, 2020, 1:48pm UTC](https://forum.graphviz.org/t/getting-layers-to-work-with-svg/107/8 "2020-05-22T13:48:16Z")

</div>

I’ve filed [Add support for layers · Issue #164 · magjac/d3-graphviz · GitHub](https://github.com/magjac/d3-graphviz/issues/164). Some day I might actually work on it.
