3

Here is the problem,

I need to create an image file with a .svg file. I have a function which should draw the svg, and then, i get it from a canvas to save it as an image file.

my draw function is :

function drawInlineSVG(ctx, rawSVG, callback) {
    var svg = new Blob([rawSVG], {type:"image/svg+xml;charset=utf-8"});
    var domURL = self.URL || self.webkitURL || self;
    var url = domURL.createObjectURL(svg);
    var img = new Image();
    img.src = url;
    console.log("URL : "+url);
    img.onLoad = function () {
        console.log("image onload");
        ctx.drawImage(this, 0, 0);     
        domURL.revokeObjectURL(url);
        callback(this);
    };
}

ctx is the canvas 2d context, rawSVG is the svg contents The console gives an url like this :

blob:http://myWebsite.net/521a72ea-3156-4290-ae16-025a8f8275bc

But the img ONLOAD never fires... so i have no callback and functions stop. I'm not working on local, so the problem does not come from getting local file...

Thanks for help!

Julo0sS
  • 2,096
  • 5
  • 28
  • 52

3 Answers3

5

Use addEventListener intead of the onLoad (what is typed incorrectly, see at the end) property:

function drawInlineSVG(ctx, rawSVG, callback) {
    var svg = new Blob([rawSVG], {type:"image/svg+xml;charset=utf-8"});
    var domURL = self.URL || self.webkitURL || self;
    var url = domURL.createObjectURL(svg);
    var img = new Image();
    img.src = url;
    img.addEventListener('load', function () {
        console.log("image onload");
        ctx.drawImage(this, 0, 0);     
        domURL.revokeObjectURL(url);
        callback(this);
    });
}

You could use use Data URL instead of blob, but that is up to you:

function drawInlineSVG(ctx, rawSVG, callback) {
    var img = new Image();
    img.src = 'data:image/svg+xml;utf8,' + rawSVG;
    img.addEventListener('load', function () {
        console.log("image onload");
        ctx.drawImage(this, 0, 0);     
        domURL.revokeObjectURL(url);
        callback(this);
    });
}

http://jsfiddle.net/smkuLrbu/

If it's not working the issue probably is your SVG file. It must contains at least the following property in the <svg> tag:

<svg xmlns="http://www.w3.org/2000/svg" ...

If you want to stick with the property, use the correct version which don't have uppercase letters: img.onload, but you really should use addEventListener.

Luizgrs
  • 4,765
  • 1
  • 22
  • 28
  • can you please explain how I could use dataURL instead? i tried with eventListener (and I already tried with onload instead of onLoad, but nothing changes...) – Julo0sS Dec 23 '14 at 12:13
  • not working with your dataURL thing neither... but guess it should come from the "url" var which does not exist anymore... BUT, log "image onload" does not appear... so... idk where it comes from... – Julo0sS Dec 23 '14 at 12:17
  • it does work, I noticed that if the SVG is missing some properties it does not load. editted the answer. – Luizgrs Dec 23 '14 at 12:24
  • SO, FINALLY :) The problem did not come from the svg tag, it came from my – Julo0sS Dec 23 '14 at 12:48
  • As [one other answer](https://stackoverflow.com/a/27619736/1619432) points out, observe the order (handler first, then data). At least from a local file, the handler might never fire otherwise. A test with the different options: https://jsfiddle.net/ewa7foe4/ does not show much difference, but it is remote. Also interesting: [JavaScript Event Listeners vs Event Handlers](https://stackoverflow.com/questions/2215379/javascript-event-listeners-vs-event-handlers). – handle Apr 11 '18 at 08:17
2

You need to set the onload before setting the url.

Otherwise the url is probably already loaded by the time you set the callback.

Try this:

function drawInlineSVG(ctx, rawSVG, callback) {
    var svg = new Blob([rawSVG], {type:"image/svg+xml;charset=utf-8"});
    var domURL = self.URL || self.webkitURL || self;
    var url = domURL.createObjectURL(svg);
    var img = new Image();

    img.onLoad = function () {
        console.log("image onload");
        ctx.drawImage(this, 0, 0);     
        domURL.revokeObjectURL(url);
        callback(this);
    };

    img.src = url;
    console.log("URL : "+url);
}
A. Rama
  • 903
  • 8
  • 18
0

see a demo here:have commented few things which i do not have.

  function drawInlineSVG(ctx) {
    // var svg = new Blob([rawSVG], {type:"image/svg+xml;charset=utf-8"});
     var domURL = self.URL || self.webkitURL || self;
     var url = 'https://mdn.mozillademos.org/files/5395/backdrop.png';
     console.log("URL : "+url);
      var img = new Image();
        img.onload = function(){
          console.log("image onload");
                   alert('inside image onload');
          ctx.drawImage(this, 0, 0);     
          domURL.revokeObjectURL(url);
          callback(this);
        };
        img.src = 'https://mdn.mozillademos.org/files/5395/backdrop.png';

     console.log("URL : "+url);
 }

var canvas = document.getElementById('canvas');
   var ctx = canvas.getContext('2d');
   drawInlineSVG(ctx);
 <canvas id="canvas" width="500px" height="400px"></canvas>
Suchit kumar
  • 11,809
  • 3
  • 22
  • 44