How to draw an inline SVG on a canvas?

For one of my projects, I needed to read pixel data from a dynamically drawn SVG, but I didn’t know how to transfer it to a canvas, which we first have to do before extracting pixel data.

I’ll explain the method that I used, so, this is what we must have at the beginning:

A <div> with an inline SVG. We have four rectangles lined-up.

<div id="box-svg">
  <svg id="svg" style="position: relative; left: 0; width: 100%; height: 100%;">
    <rect fill="rgb(136, 0, 68)" width="25%" height="100%" x="0" y="0" />
    <rect fill="rgb(230, 0, 115)" width="25%" height="100%" x="25%" y="0" />
    <rect fill="rgb(255, 91, 173)" width="25%" height="100%" x="50%" y="0" />
    <rect fill="rgb(255, 183, 219)" width="25%" height="100%" x="75%" y="0" />
  </svg>
</div>

Then we have a <div> with our canvas. This is where we will draw our SVG on.

<div id="box-canvas">
  <canvas id="canvas"></canvas>
</div>

The styles. Put them in the <head> section:

body{
  margin: 0;
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  align-items: center
}
#box-svg, #box-canvas{
  width: 90%;
  height: 10%;
}
canvas{
  width: 100%;
  height: 100%
}

Now let’s start out. Throw in all the lines from this point forward inside a <script> tag with type='text/javascript‘ right before </body>.

First we pick up the canvas, and specify width and height for it:

(Find out why we didn’t do this in our CSS at the end of the tutorial.)

let canvas = document.getElementById('canvas');

canvas.width = document.getElementById('box-canvas').offsetWidth;
canvas.height = document.getElementById('box-canvas').offsetHeight;

Next, we call getContext('2d') which returns an object with all the methods and properties that we can use to draw on canvas.

let context = canvas.getContext('2d');

Now, what we need to draw happens to be an inline SVG, but the problem is that the method we are supposed to use, drawImage() does not accept them!

So, something that we can do is turning the inline SVG into a data URL:

For that, first we use XMLSerializer().serializeToString() for a string which represents our SVG in XML form.

let svgURL = new XMLSerializer().serializeToString(document.getElementById('svg'));

We then create an <img>,

let img = document.createElement('img');

and then we can call drawImage() from img.onload, and specify the src for the <img> afterwards. Note that we have encoded the URL for the svg:

img.onload = function(){
  context.drawImage(img, 0,0);
}

img.src = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgURL);

And that’s it!

You can find the complete code and the demo here on GitHub.

And learn in my next tutorial why we better not specify canvas dimensions in CSS.