TypeMismatchError in drawImage()

I'm using drawImage(). This is my code. imDiv holds an inline svg.

  var c =document.getElementById( 'cvs' );
  var ctx =c.getContext( '2d' );
  var img =document.getElementById( 'imDiv' );
   ctx.drawImage( img, 0, 0 );  //TypeMismatchError

I'm getting a TypeMismatchError error. What might be the reason and How can I fix this?

enter image description here

Answers:

Answer

You must convert the SVG to an image first, then draw the image to canvas.

There are some things you need to take into consideration:

  • The SVG must be well-formed (think XML)
  • The first element in the SVG must be xmlns attributed
  • There are variable security restrictions depending on browser when it comes to foreignObject (to embed HTML etc.). It will work in some (Firefox, without external references), others not so much (f.ex. Chrome). This is currently in a state of vacuum, and we can't do much about it on client side

Here is one way of doing this:

// Inline SVG:
var svg = document.querySelector('svg').outerHTML,  // make sure SVG tags are included
  canvas = document.querySelector('canvas'),        // target canvas
  ctx = canvas.getContext('2d');

// convert to image (see function below)
// converting to image is an asynchronous process, so we need a callback
svgToImage(svg, function(img) {

  // HERE you could insert the image to DOM:
  // var myElement = document.getElementById(elementID);
  // myElement.appendChild(img);
  
  // set canvas size = image
  canvas.width = img.width;
  canvas.height = img.height;

  // draw SVG-image to canvas
  ctx.drawImage(img, 0, 0);
});

// this will convert an inline SVG to a DATA-URI
function svgToImage(svg, callback) {
  var url = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svg),
      img = new Image;

  // handle image loading, when done invoke callback
  img.onload = function() {
    callback(this);
  };

  img.src = url;
}
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
  <linearGradient id="gradient">
    <stop offset="0%" stop-color="#00f" />
    <stop offset="100%" stop-color="#f70" />
  </linearGradient>
  <rect fill="url(#gradient)" x="0" y="0" width="100%" height="100%" />
</svg>

<br>
<canvas></canvas><br>

Answer

As of now, it's impossible to draw div or svg elements onto the canvas. The first argument passed to context.drawImage() must be an Image, canvas, or even a video element (using the svg is probably causing the TypeMismatchError).

So you'll have retrieve an actual Image on the document with getElementById() or create one with new Image().

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.