vis.js library - Rendering a network of nodes with svg and custom html
Asked Answered
P

1

6

I'm working with the vis.js library, and rendering nodes with custom HTML via the svg tag.

My online project is at: https://stackblitz.com/edit/visjs-with-angular

The problem I'm having is when I attempt to add an image to the div, which is inside an svg.

You can see the vis.component.ts in the 'app\app\vis' folder of my project, and its associated HTML view file.

In the drawSvgNetwork() function you will see where I build out the SVG. I figured I'd be able to add a <i> tag with a background-image url, but it doesn't seem to be rendering when vis.js renders the nodes:

var svg = '<svg xmlns="http://www.w3.org/2000/svg" width="390" height="65">' +
          '<rect x="0" y="0" width="100%" height="100%" fill="#7890A7" stroke-width="20" stroke="#ffffff" ></rect>' +
          '<foreignObject x="15" y="10" width="100%" height="100%">' +
          '<div xmlns="http://www.w3.org/1999/xhtml" style="font-family:Arial; font-size:30px">' +
          ' <em>I</em> am' +
          '<span style="color:white; text-shadow:0 0 20px #000000;">' +            
            ' HTML in SVG!</span>' +

          // * THIS IMAGE IS NOT RENDERING * 
          '<i style="background-image: url(https://openclipart.org/download/280615/July-4th-v2B.svg);"></i>' +

          '</div>' +
          '</foreignObject>' +
          '</svg>';

i.e. Here is what you will see when running my online project.

visjs network of nodes.

*For reference:

The full online examples are at: https://visjs.github.io/vis-network/examples/ And the specific demo page is here (view source to see js code): https://visjs.github.io/vis-network/examples/network/nodeStyles/HTMLInNodes.html

Pavia answered 29/11, 2018 at 16:15 Comment(0)
C
5

Looks like with visjs it's not possible to load an external image inside an SVG, nor in <foreignObject>, neither in <Image> tag. Here is an open issue for the problem on github: Image tag is not loading inside the svg

The maintainer of the repository answered that it was not possible.

A workaround can be found in the same thread (but it may not be suitable for you): the idea is to load the image separately and render it as dataUrl

Loading the svg image and converting it to dataUrl:

  loadImage(url) {
    const img = new Image();

    img.crossOrigin = "anonymous";
    img.src = url;

    return Observable.fromEvent(img, 'load')
        .map((e: Event) => {
            const canvas = document.createElement('canvas');
            canvas.getContext('2d').drawImage(e.target as HTMLImageElement, 0, 0);
            const dataURL = canvas.toDataURL();
            return dataURL;
        })
  }

Using the acquired dataUrl as background instead of the direct svg file url:

  '<i style="background-image: url(' + dataUrl + '); display: inline-block; width: 40px; height: 20px; background-size: contain;"></i>' +

Here is the corrected project https://stackblitz.com/edit/visjs-with-angular-m63jme (I also replaced the svg file, which was used in the original project and contained a US flag, with another arbitrary svg to avoid issues in FF, see below)

FF issues with rendering svg on canvas

Firefox has some issues with rendering an svg file on canvas, when the file contains width and height attributes specified as percentages. See the SO questions for more details: 1, 2. So be sure to use an svg with width and height attributes that are not percentages.

Cauthen answered 1/10, 2019 at 10:41 Comment(6)
this certainly looks like a viable option. I will circle back to my old issue at some point and try this out. Much appreciated.Pavia
I see you are loading the US flag svg, but I'm not seeing it rendered anywhere - i.e. this.loadImage('https://openclipart.org/download/280615/July-4th-v2B.svg').subscribe( (dataUrl) => this.drawSvgNetwork(dataUrl) // DRAW SVG WITH CUSTOM HTML );Pavia
It definitely gets rendered OK in Chrome (see the screenshot prnt.sc/pkut0w), but I have just checked with FF, and surprisingly the flag is missing :P Will look into that. (BTW what browser are you using?)Cauthen
Fixed the project and added an explanation to the answer.Cauthen
Great stuff, thanks ! I can see that the dataUrl idea you had works great. I still can't believe I posted this almost a year ago ! THANK YOU.Pavia
No problem, glad I could helpCauthen

© 2022 - 2024 — McMap. All rights reserved.