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) 或 canvas2image或 fileSaver 或 canvasToBLob 库 - 结果是相同的:一个没有 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>
我正在尝试将 canvas 从网页保存到文件中。
canvas 非常复杂,由多个图像构建而成(几个 semi-transparent .png 文件、2 个 svg 元素和其他 4 个 canvases),无论我如何尝试保存它,使用 canvas.toDataURL()
方法或使用 domtoimage [library] (https://github.com/tsayen/dom-to-image) 或 canvas2image或 fileSaver 或 canvasToBLob 库 - 结果是相同的:一个没有 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>