Canvas 另存为图像 [canvg - 在 canvas 上渲染 svg]

Canvas save as image [canvg - rendering svg on canvas]

我正在尝试将 canvas 从网页保存到文件中。 canvas 非常复杂,由多个图像构建而成(几个 semi-transparent .png 文件、2 个 svg 元素和其他 4 个 canvases),无论我如何尝试保存它,使用 canvas.toDataURL() 方法或使用 domtoimage [library] (https://github.com/tsayen/dom-to-image) 或 canvas2imagefileSavercanvasToBLob 库 - 结果是相同的:一个没有 svg( 和 <image> 元素的图像) 部分。所以我只得到了从 canvas 构建的零件。我阅读了 'tainted' canvases,但图像托管服务器与网页相同。

此外,我很困惑,因为如果我通过单击 RCM 并选择 "Save image as" 功能来保存 canvas - 它保存的正是我需要的 - 完整图片。

整个代码量很大,保存方式也各不相同,这里只放一个保存方式:

domtoimage.toBlob(canvasElement)
  .then(function (blob) {
    console.log(blob);
    window.saveAs(blob, 'my-node.png');
  });

左边的图片是在浏览器中使用“另存为”功能时得到的图片,右边的是js通过[=29]保存的图片=]toBlob

很乐意得到有关如何自动保存完整图像的任何建议:)

我会利用你编辑的机会 post 这是一个真正的答案,因为你基于你的答案(你应该 post 编辑为自我回答 b.t.w) 关于地雷的评论,要求您提供更多说明。

因此,正如我们发现的那样,您的问题是当您调用导出方法时并非所有图像 loaded/drawn,因此,这些图像在输出中丢失。

canvg函数及其快捷方式ctx.drawSvg可以是异步的。通常情况下,当只渲染形状时它不是同步的,但由于您在这里加载外部内容,包裹在 SVGImage (<image>) 元素中,它不能同步。

但是,有一个 renderCallback 选项可以添加到您的 canvg 调用中。由于您确实使用了 ctx.drawSVG,并且与原始 canvg 相比,此方法有一些额外的参数(dx、dy、dwidth、dheight),因此您需要这样调用它:

ctx.drawSvg(yourSVGMarkup, 0, 0, null, null, {renderCallback: yourCallbackFunction}); 

var str = new XMLSerializer().serializeToString(document.querySelector('svg'));
canvas.getContext('2d').drawSvg(str, 0, 0, null, null, {
  renderCallback: function() {
    console.log('done');
  }
});
console.log('doing');
<script src="https://cdn.rawgit.com/canvg/canvg/master/canvg.js"></script>
<svg width="300" height="150" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <image xlink:href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png" x="0" y="0" height="100" width="100" />
</svg>
<canvas id="canvas"></canvas>