简体   繁体   English

使用非常大的SVG转换为PNG <canvas>

[英]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. 我试图将一个大的SVG(它的数据URL大约是750000 - 1000000个字符)转换为PNG,方法是将它的数据url传递到一个图像并进入画布,但图像只加载大约1/4的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: 我已经尝试实现canvg来绘制SVG,但DataURL生成的结果为空白图像:

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: 我现在相当确信画布无法绘制整个图像,因为我尝试实现Blob解决方案达到同样的效果:

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. 图像再次加载正常并转到URL(在它被撤销之前)也显示图像正常。

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? 画布dataURL的长度不一致,所以我不认为这是最大限度的,有没有办法检测画布大小? The application is only supported for Chrome and FireFox. 该应用程序仅支持Chrome和FireFox。

Working fiddle. 工作小提琴。

HTML: 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: 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? 为什么图像只加载大约1/4的SVG?

Answer: 回答:

Just follow these rules: 只需遵循以下规则:

  1. x of <rect/> + width of <rect/> <= width of <svg/> x<rect/> + width<rect/> <= width<svg/>
  2. y of <rect/> + height of <rect/> <= height of <svg/> y<rect/> + height<rect/> <= height<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 这里, x <rect/> = 10 ,宽度<rect/> = 550 ,宽度<svg> = 500

so, 10 + 550 > 500 所以, 10 + 550 > 500

In this case image will be partially rendered. 在这种情况下,将部分渲染图像。

Hope this will solve your problem. 希望这能解决你的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM