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

mat*_*189 13 javascript svg canvas

我试图将一个大的SVG(它的数据URL大约是750000 - 1000000个字符)转换为PNG,方法是将它的数据url传递到一个图像并进入画布,但图像只加载大约1/4的SVG.

通过创建:

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
Run Code Online (Sandbox Code Playgroud)

编辑

我已经尝试实现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');
Run Code Online (Sandbox Code Playgroud)

我使用过的方法有什么问题吗?

进一步编辑

我现在相当确信画布无法绘制整个图像,因为我尝试实现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   
Run Code Online (Sandbox Code Playgroud)

图像再次加载正常并转到URL(在它被撤销之前)也显示图像正常.

画布dataURL的长度不一致,所以我不认为这是最大限度的,有没有办法检测画布大小?该应用程序仅支持Chrome和FireFox.

Kha*_*ain 3

工作小提琴。

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>
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

你的问题:

为什么图像只加载 SVG 的 1/4 左右?

回答:

只需遵循以下规则:

  1. x<rect/>+的< =width<rect/>width<svg/>
  2. y<rect/>+的< =height<rect/>height<svg/>

例如:

<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>
Run Code Online (Sandbox Code Playgroud)

这里,=x的宽度,=的宽度,=的宽度<rect/>10<rect/>550<svg>500

所以,10+ 550>500

在这种情况下,图像将被部分渲染。

希望这能解决您的问题。