How to handle image hosted on a server with d3-graphviz ( if it's implemented )?

Hi,

In Graphviz, thanks to the image attribute we can specify a file containing an image to be displayed inside a node like :

digraph{
    a[shape="rectangle" image ="c:/path/to/file.svg"]    
}

But how to adapt that with d3-graphviz ?
I tried with some hope :

digraph{
    a[shape="rectangle" image ="http://myserver/file.svg"]    
}

But it’s not working and when I open the browser console I don’t have any errors.
And the SVG node doesn’t have any trace of the file.
Of course, when I browse to http://myserver/file.svg it displays the image.

I have tried with the Graphviz Visual Editor but so far did not find the solution.

Is it possible to display an image inside a node with d3-graphviz?

Thanks for your help.

That feature was removed, to reduce security problems. I’m not sure if you can process the SVG output of graphviz to try to make that idea work anyway, but graphviz expects to load external shapes so it can discover sizes and be able to write graphics output in all the supported formats. You could write your own wrapper to fetch shapes and put them in local files. You have to ask, though, what security risks could be opened that way.

Actually, I have already processed the SVG output of graphviz.

Let’s say the 2 graphs are ( simple case ) :

digraph  {  
    layout="dot"  
     a[shape="circle"  image="dist/icons/icon1.svg" label=""] ;  
 }

digraph  {  
     layout="dot"  
     a[ shape="circle"  image="dist/icons/icon1.svg" label=""] ;  
     a -> b
     b[ shape="circle"  image="dist/icons/icon2.svg" label=""] ;
 }

the path dist/icons/icon1.svg is a local path on the server. From here I just output the SVG format
and I just modify the xlink:href attribute of the image element in order to match the network path.

So far so good, the problem is that I would like to use d3-graphviz for the transition between graphs
As far as I know, I have to specify the sequence of graphs like so :

const gv1  = `digraph  {  
    layout="dot"  
     a[shape="circle"  image="dist/icons/icon1.svg" label=""] ;  
 }`;
const gv2 = `digraph  {  
     layout="dot"  
     a[ shape="circle"  image="dist/icons/icon1.svg" label=""] ;  
     a -> b
     b[ shape="circle"  image="dist/icons/icon2.svg" label=""] ;
 }`;
const graphs = [gv1,gv2]

and then this code use d3-graphviz

import * as d3             from 'd3'
export function demo1(selector,graphs=[]){
    let index     = 0;
    let canChange = true;  
    document.addEventListener('keydown', logKey);
    document.addEventListener('keyup', onKeyup);
    const transition =  () => d3.transition("demo1").ease(d3.easeLinear).delay(100).duration(500);  
    const condition  =  (e)=> (e.code ==="ArrowRight" || e.code ==="ArrowLeft")
    function onKeyup(e){  
        if(!condition(e))return;
         canChange = true
     }  
    function logKey(e) {
       if(!condition(e))return;
       if(!canChange)return;
       if(e.code ==="ArrowRight" && index < (graphs.length-1)) index+=1 ;
       if(e.code ==="ArrowLeft"  &&  index > 0)  index-=1 ;
       canChange = false
       graph.transition(transition).renderDot(graphs[index]);
    }
    const graph     = d3.select(selector).graphviz(selector);
    graph.renderDot(graphs[index]);  
}

Just two listeners to go back and forth between graphs, It works but no Icons…

And from here I don’t know what to do because I have no errors and the image element is not even generated in the SVG output. Furthermore, I am not aware of wasm ( d3-graphviz has a dependency with @hpcc-js/wasm ), so I don’t know how to adapt my work to make it work with d3-graphviz and get all the nice transitions.

This picture of the web page and the console demonstrates what I am saying.

Hope I was clear.

oops Sorry !! all my fault,

I missed the documentation… and it’s actually pretty clear!
here is the link : d3-graphviz - npm
final code :

import * as d3             from 'd3'
export function demo1(selector){
    let index     = 0;
    const gv1  = `digraph  {
        layout="dot"  
         a[shape="circle"  image="icons/icon1.svg" label=""] ;  
     }`;

    const gv2 = `digraph  {  
         layout="dot"  
         a[ shape="circle"  image="icons/icon1.svg" label=""] ;  
         a -> b
         b[ shape="circle"  image="icons/icon2.svg" label=""] ;
     }`;

    const graphs = [gv1,gv2]
    let canChange = true;  
    document.addEventListener('keydown', onKeydown);
    document.addEventListener('keyup', onKeyup);
    const transition =  () => d3.transition("demo1").ease(d3.easeLinear).delay(100).duration(500);  
    const condition  =  (e)=> (e.code ==="ArrowRight" || e.code ==="ArrowLeft")
    function onKeyup(e){  
        if(!condition(e))return;
         canChange = true
     }  

    function onKeydown(e) {
       if(!condition(e))return;
       if(!canChange)return;
       if(e.code ==="ArrowRight" && index < (graphs.length-1)) index+=1 ;
       if(e.code ==="ArrowLeft"  &&  index > 0)  index-=1 ;
       canChange = false
       graph.transition(transition).renderDot(graphs[index]);

    }

    const graph     = d3.select(selector).graphviz(selector);
    graph
    .addImage("icons/icon1.svg","300px","300px")
   .addImage("icons/icon2.svg","300px","300px")
    .renderDot(graphs[index]);  

}

this is the important part :

    graph 
    .addImage("icons/icon1.svg","300px","300px")
   .addImage("icons/icon2.svg","300px","300px")
    .renderDot(graphs[index]);

Of course, the code is not perfect, but at least it gives a simple example of how to have 2 graphs with images and a nice transition between them with key controls

1 Like