Convert very large SVG to PNG using <canvas>

I'm trying to convert a large SVG (it's data URL is about 750000 - 1000000 characters) to a PNG by passing it's data url through an image and into a canvas but the image is only loading about 1/4 of the SVG.

Creating via:

var svg_xml = (new XMLSerializer()).serializeToString(svg),
    url = 'data:image/svg+xml;base64,' + btoa(svg_xml);

var img = new Image();
img.width = 730;
img.height = 300;
img.onload = function(){
    var canvas = document.create('canvas');
    canvas.width = 730;
    canvas.height = 300;

    var ctx = canvas.getContext('2d');
    ctx.drawImage(img, 0, 0, 730, 300);

    callbackFn(canvas.toDataURL('image/png');
}
img.src = url

Edit

I've tried implementing canvg to draw the SVG but the DataURL produced results in a blank image:

var svg_xml = (new XMLSerializer()).serializeToString(svg);
var canvas = document.createElement('canvas');
canvas.width = 730;
canvas.height = 300;

var ctx = canvas.getContext('2d');
ctx.drawSvg(svg_xml, 0, 0, 730, 300);
callbackFn(canvas.toDataURL('image/png');

Is there anything wrong with the method I've used?

Further Edit

I'm now fairly convinced that it's the canvas failing to draw the whole image as I tried implementing a Blob solution to the same effect:

var svg_xml = (new XMLSerializer()).serializeToString(svg),
    blob = new Blob([svg_xml], {type:'image/svg+xml;charset=utf-8'}),
    url = window.URL.createObjectURL(blob);

var img = new Image();
img.width = 730;
img.height = 300;
img.onload = function(){
    var canvas = document.create('canvas');
    canvas.width = 730;
    canvas.height = 300;

    var ctx = canvas.getContext('2d');
    ctx.drawImage(img, 0, 0, 730, 300);

    window.URL.revokeObjectURL(url);
    callbackFn(canvas.toDataURL('image/png');
}
img.src = url   

The image again loads fine and going to the URL (before it's revoked) displays the image fine as well.

The length of the canvas dataURL is not consistent so I don't think that's maxing out, is there a way of detecting the canvas size? The application is only supported for Chrome and FireFox.


Working fiddle.

HTML:

    <div>
        <svg xmlns="http://www.w3.org/2000/svg"
              width="526" height="233">
          <rect x="13" y="14" width="500" height="200" rx="50" ry="100"
              fill="none" stroke="blue" stroke-width="10" />
        </svg>
        <a id='imgId'>Save</a>
    </div>
    <canvas></canvas>

JavaScript:

var svg = document.getElementsByTagName('svg')[0];
var svg_xml = (new XMLSerializer()).serializeToString(svg),
    blob = new Blob([svg_xml], {type:'image/svg+xml;charset=utf-8'}),
    url = window.URL.createObjectURL(blob);

var img = new Image();
img.width = 730;
img.height = 300;
img.onload = function(){
    var canvas = document.createElement('canvas');
    canvas.width = 730;
    canvas.height = 300;

    var ctx = canvas.getContext('2d');
    ctx.drawImage(img, 0, 0, 730, 300);

    window.URL.revokeObjectURL(url);
    var canvasdata = canvas.toDataURL('image/png');
    var a = document.getElementById('imgId');
    a.download = "export_" + Date.now() + ".png";
    a.href=canvasdata;   
}
img.src = url

Your question:

Why image is only loading about 1/4 of the SVG?

Answer:

Just follow these rules:

  • x of <rect/> + width of <rect/> <= width of <svg/>
  • y of <rect/> + height of <rect/> <= height of <svg/>
  • For example:

    <svg xmlns="http://www.w3.org/2000/svg" width="500" height="200">
         <rect x="10" y="10" width="550" height="250" rx="50" ry="100"
                      fill="none" stroke="blue" stroke-width="10" />
    </svg>
    

    Here, x of <rect/> = 10 , width of <rect/> = 550 , width of <svg> = 500

    so, 10 + 550 > 500

    In this case image will be partially rendered.

    Hope this will solve your problem.

    链接地址: http://www.djcxy.com/p/50326.html

    上一篇: 即使在调整大小后也可以下载原始画布

    下一篇: 使用<canvas>将非常大的SVG转换为PNG