Skip to main content

Generating output with html2canvas and JsPlumb

· 4 min read
Simon Porritt
JsPlumb core team

html2canvas is a project that's been around for quite some time now and over the years we've seen people have varying degrees of success using it with JsPlumb. This week we decided to take a look and see if we could get it to work, and the good news is that we could... except with one minor caveat: you'll have to use our patched version of the library (@jsplumb/html2canvas). More on that below.

Drag the boxes around until you have something you like and then hit Export. The contents of the JsPlumb instance will be rendered into a canvas element below.

IMPORTS

As mentioned above, you'll need our patched version of html2canvas:

npm install --save @jsplumb/html2canvas

EXPORTING A CANVAS

Working with html2canvas is pretty straightforward. This is the function we use in the above demo to get the output:


import html2canvas from "@jsplumb/html2canvas";

function doExport(surface) {
surface.zoomToFit()
html2canvas(surface.container).then((canvas) => {
// canvas is an HTML Canvas into which the export has been rendered.
})
}

As it says in the code there, canvas is an HTMLCanvasElement.

Do you notice, though, in the demo above that since we call zoomToFit() before we do the export, we actually change what the user is looking at and we don't restore it. We can improve the function a little by stashing the pan/zoom prior to the export and reinstating them afterwards:

function doExport() {
const p = s.getPan(), z = s.getZoom()
s.zoomToFit()
html2canvas(s.container).then((canvas) => {
s.setPanAndZoom(p.x, p.y, z, false)
// do something with the canvas
})
}

That's a little better. It's not awesome how the display jumps but html2canvas faithfully reproduces the input it is given; perhaps a decent approach in production might be to arrange to mask the JsPlumb canvas while you're running the export.

EXPORTING TO AN IMAGE

Since the output of html2canvas is a Canvas element, you're probably going to want to get that canvas as an image. There are a whole bunch of libraries that offer utilities to do this - basically it's just a case of calling toDataURL() on the canvas and creating an image with it. We published a canvas processing library ourselves a few months ago, as part of our Image Processing Pipeline demonstration, which offers a canvasToImage method:

/**
* Extracts the contents of the given canvas to an Image.
* @param canvas
* @param type Type of image (eg image/png, image/jpeg). Defaults to PNG.
* @param quality When exporting JPG, this defines the quality of the output.
*/
export function canvasToImage(canvas: HTMLCanvasElement, type?: string, quality?: number): Promise<HTMLImageElement>;

The code for that is on Github at https://github.com/jsplumb/canvas-image-processing, and you can install it via

npm install @jsplumb/canvas-image-processing

but in our final demo on this page we've gone for a bit of a brute force approach - we've setup an <a> element configured for launching a download, and when our canvas is ready we set its contents as the anchor's href, and then we fake a click on it:

<div>
<button onClick={() => doExport()}>Export</button>
<button onClick={() => clear()}>Clear</button>
<a download="jsplumb.png" href="" ref={linkRef}></a>
</div>

import html2canvas from "@jsplumb/html2canvas";

const linkRef = useRef(null)

function doExport(surface) {
const p = surface.getPan(), z = surface.getZoom()
surface.zoomToFit()
html2canvas(s.container).then((canvas) => {
s.setPanAndZoom(p.x, p.y, z, false)
linkRef.current.setAttribute("href", canvas.toDataURL("image/png"))
linkRef.current.click()
})
}

This is React code, so the <a> element is wired up as a ref, but the principle is the same with plain DOM elements.

HTML2CANVAS PATCH

I mentioned above that we had to patch html2canvas in order to get it to work with JsPlumb. For those interested, I raised this issue to track the problem, and from that issue you can navigate through to JsPlumb's fork. Ideally this fix would find its way in to html2canvas and we could throw away our patch, but I'm not sure at this point if the project maintainer is active on it.

To install our patched version:

npm install --save @jsplumb/html2canvas

FURTHER READING

If you like fun canvas based demos, try our Image Processor starter app

Start a free trial

Sending your evaluation request...

Interested in the concepts discussed in this article? Start a free trial and see how JsPlumb can help bring your ideas to market in record time.


GET IN TOUCH

If you'd like to discuss any of the ideas/concepts in this article we'd love to hear from you - drop us a line at hello@jsplumbtoolkit.com.