如何从复杂的 svg 正确生成 canvas
How to properly generate canvas from complex svg
我正在尝试从我的网站导出一个复杂的 SVG 块(用 c3 生成)作为图像(无论是 png、svg、pdf,此时我愿意接受任何解决它的方法,尽管 vector格式将是理想的)。
我已经尝试了 html2canvas、canvg、jsPDF,以及该帮派的所有酷孩子。
问题是:我的一个情节都搞砸了。线变成区域,区域被反转,颜色被破坏,......你的名字。
我离成为 js 专家还有很远。我刚到这里,正在摸索中,有的还请多多包涵。
我不知道这是 CSS 问题还是什么。是的,html 后面确实有 CSS。
我的临时解决方案是使用jQuery.print.js 调用我的div 的打印。这远非理想,原因有很多:
没有bbox。它生成页面大小由用户定义的 PDF,而不是图像大小;
我正在使用 bootstrap 具有自动调整大小的卡片。每当按下 "print image" 时,打印将使用当前尺寸。我试过隐藏卡片以重新调整目标卡片的大小,但调整大小只会在打印调用之后进行,原因我不得而知。如果这个问题解决了,这个临时解决方案会更好,虽然还是临时的。
所以,一个问题是:
- 如何获取如图所示的 SVG?
- 或者,如何在调用打印之前调整卡片的大小?
- 或者,如何生成光栅 (png/jpeg) 而没有从 canvg/jsPDF 获得的格式错误?
现在执行打印调用的函数是:
function getscreenshot(div) {
// Hide row pair:
$('#map-card').addClass('hidden');
// Temporarily change class attr to spawn all row:
var divClass = $(div).attr('class');
$(div).attr('class', 'col');
// ****PROBLEM****
// Div size is not upated before calling print()
// causing the print to have the size as displayed on user screen
// How to refresh it before print?
// ********
// jQuery.print solves it in a non-ideal way, since user has to set save as file and so on
$(div).print();
// This solution with jsPDF produces **ugly as hell** image:
// var pdf = new jsPDF('landscape');
// pdf.addHTML(document.getElementById(div), function() {
// pdf.save(name + 'pdf');
// });
// Recover original size after print:
// Restore row pair and div original state:
$('#map-card').removeClass('hidden');
$(div).attr('class', divClass);
}
这是网页上显示的一排卡片:
右边的图是我关注 try-outs 的图,也是正在完成未格式化的图。
检查使用 html2canvas、jsPDF 等会导致与 fiddle with SVG pasted 中相同的错误构造,使用 canvg.js
PS:是的,我搜索了很多。这就是我最终尝试 html2canvas、canvg、jsPDF、jqprint、...
的方式
干杯!
您可以通过 Mike Bostock 的(或者可能是纽约时报的)SVG Crowbar 解决问题。使用 SVG Crowbar 2。将它拖到书签栏,然后在要保存 SVG 的页面上单击它。如果有多个 SVG,则必须选择哪一个。
我用 c3.js 测试了 SVG Crowbar 1,它没有正确保存样式,所以请确保你使用 SVG Crowbar 2。我用 c3.js 测试了 SVG Crowbar 2,它适用于我.
获得 SVG 后,您可以使用 Inkscape 将其制作成 PNG。
单击:文件 > 导出 PNG 图像。
然后选择您想要的输出尺寸。
然后单击“导出”。
This 网站有详细的操作步骤
还有一些在线网站也可以将 SVG 转换为 PNG,但有一些网站所以我不会 post 链接。 google 搜索应该可以找到您需要的内容。
如果您想以编程方式完成所有这些,那就是另一回事了。
更新:SVG Crowbar(1 和 2)仅适用于 chrome。
最终结果使用了@tgiachetti 的答案,并进行了一些调整。原始 svg-crowbar-2 的问题在于它是一本小册子并打开了网站上所有 SVG 的下载按钮,这不是预期的最终结果,并且仅适用于 Chrome.
此处介绍的解决方案适用于 Chrome 和 Firefox。
所以我最终对 https://github.com/NYTimes/svg-crowbar 的 svg-crowbar-2.js 进行了一些修改:
- 作为函数使用,不是小册子;
- 只循环到第 4 个 SVG 源,因为不需要其余的;
- 接收单图下载的 SVG 序号;
- 下载后重新加载页面。
可以在 js 文件 singledownload-svg-crowbar-2.js 中找到更改:https://github.com/FluVigilanciaBR/fludashboard/blob/development/fludashboard/static/libs/svg-crowbar-2/singledownload-svg-crowbar-2.js
用法:
首先,插入调整后的 svg-crowbar-2 作为源:
<script src="./static/libs/svg-crowbar-2/singledownload-svg-crowbar-2.js"></script>
然后,在每个绘图卡上我插入一个按钮,调用函数 getscreenshot 传递所需 SVG 的序列号:
<div class="container">
<button type="button" class="btn btn-link btn-sm no-print" onclick="getscreenshot(3);">Salvar imagem</button>
</div>
此函数位于 index.html 本身,基本上根据绘图序号定义 SVG 文件名,并调用在 singledownload-svg-crowbar-2.js 上定义的单个 SVG 下载器函数 singleSVGcrowbar:
<script language="JavaScript" type="text/javascript">
function getscreenshot(myplot) {
var plotName = ['mapa', 'mapa-legenda', 'serie-temporal', 'distribuicao-etaria'];
var myplotObj = {SVGid: myplot, SVGname: plotName[myplot]};
singleSVGcrowbar(myplotObj);
}
</script>
如果你想在你自己的网站上插入这个,首先通过 运行 原始 svg-crowbar-2 识别所需 SVG 块的序号。这是在调用 getscreenshot(myplot) 时插入的数字。
我正在尝试从我的网站导出一个复杂的 SVG 块(用 c3 生成)作为图像(无论是 png、svg、pdf,此时我愿意接受任何解决它的方法,尽管 vector格式将是理想的)。 我已经尝试了 html2canvas、canvg、jsPDF,以及该帮派的所有酷孩子。 问题是:我的一个情节都搞砸了。线变成区域,区域被反转,颜色被破坏,......你的名字。
我离成为 js 专家还有很远。我刚到这里,正在摸索中,有的还请多多包涵。
我不知道这是 CSS 问题还是什么。是的,html 后面确实有 CSS。
我的临时解决方案是使用jQuery.print.js 调用我的div 的打印。这远非理想,原因有很多:
没有bbox。它生成页面大小由用户定义的 PDF,而不是图像大小;
我正在使用 bootstrap 具有自动调整大小的卡片。每当按下 "print image" 时,打印将使用当前尺寸。我试过隐藏卡片以重新调整目标卡片的大小,但调整大小只会在打印调用之后进行,原因我不得而知。如果这个问题解决了,这个临时解决方案会更好,虽然还是临时的。
所以,一个问题是:
- 如何获取如图所示的 SVG?
- 或者,如何在调用打印之前调整卡片的大小?
- 或者,如何生成光栅 (png/jpeg) 而没有从 canvg/jsPDF 获得的格式错误?
现在执行打印调用的函数是:
function getscreenshot(div) {
// Hide row pair:
$('#map-card').addClass('hidden');
// Temporarily change class attr to spawn all row:
var divClass = $(div).attr('class');
$(div).attr('class', 'col');
// ****PROBLEM****
// Div size is not upated before calling print()
// causing the print to have the size as displayed on user screen
// How to refresh it before print?
// ********
// jQuery.print solves it in a non-ideal way, since user has to set save as file and so on
$(div).print();
// This solution with jsPDF produces **ugly as hell** image:
// var pdf = new jsPDF('landscape');
// pdf.addHTML(document.getElementById(div), function() {
// pdf.save(name + 'pdf');
// });
// Recover original size after print:
// Restore row pair and div original state:
$('#map-card').removeClass('hidden');
$(div).attr('class', divClass);
}
这是网页上显示的一排卡片:
右边的图是我关注 try-outs 的图,也是正在完成未格式化的图。 检查使用 html2canvas、jsPDF 等会导致与 fiddle with SVG pasted 中相同的错误构造,使用 canvg.js
PS:是的,我搜索了很多。这就是我最终尝试 html2canvas、canvg、jsPDF、jqprint、...
的方式干杯!
您可以通过 Mike Bostock 的(或者可能是纽约时报的)SVG Crowbar 解决问题。使用 SVG Crowbar 2。将它拖到书签栏,然后在要保存 SVG 的页面上单击它。如果有多个 SVG,则必须选择哪一个。
我用 c3.js 测试了 SVG Crowbar 1,它没有正确保存样式,所以请确保你使用 SVG Crowbar 2。我用 c3.js 测试了 SVG Crowbar 2,它适用于我.
获得 SVG 后,您可以使用 Inkscape 将其制作成 PNG。 单击:文件 > 导出 PNG 图像。 然后选择您想要的输出尺寸。 然后单击“导出”。 This 网站有详细的操作步骤
还有一些在线网站也可以将 SVG 转换为 PNG,但有一些网站所以我不会 post 链接。 google 搜索应该可以找到您需要的内容。
如果您想以编程方式完成所有这些,那就是另一回事了。
更新:SVG Crowbar(1 和 2)仅适用于 chrome。
最终结果使用了@tgiachetti 的答案,并进行了一些调整。原始 svg-crowbar-2 的问题在于它是一本小册子并打开了网站上所有 SVG 的下载按钮,这不是预期的最终结果,并且仅适用于 Chrome.
此处介绍的解决方案适用于 Chrome 和 Firefox。
所以我最终对 https://github.com/NYTimes/svg-crowbar 的 svg-crowbar-2.js 进行了一些修改:
- 作为函数使用,不是小册子;
- 只循环到第 4 个 SVG 源,因为不需要其余的;
- 接收单图下载的 SVG 序号;
- 下载后重新加载页面。
可以在 js 文件 singledownload-svg-crowbar-2.js 中找到更改:https://github.com/FluVigilanciaBR/fludashboard/blob/development/fludashboard/static/libs/svg-crowbar-2/singledownload-svg-crowbar-2.js
用法:
首先,插入调整后的 svg-crowbar-2 作为源:
<script src="./static/libs/svg-crowbar-2/singledownload-svg-crowbar-2.js"></script>
然后,在每个绘图卡上我插入一个按钮,调用函数 getscreenshot 传递所需 SVG 的序列号:
<div class="container">
<button type="button" class="btn btn-link btn-sm no-print" onclick="getscreenshot(3);">Salvar imagem</button>
</div>
此函数位于 index.html 本身,基本上根据绘图序号定义 SVG 文件名,并调用在 singledownload-svg-crowbar-2.js 上定义的单个 SVG 下载器函数 singleSVGcrowbar:
<script language="JavaScript" type="text/javascript">
function getscreenshot(myplot) {
var plotName = ['mapa', 'mapa-legenda', 'serie-temporal', 'distribuicao-etaria'];
var myplotObj = {SVGid: myplot, SVGname: plotName[myplot]};
singleSVGcrowbar(myplotObj);
}
</script>
如果你想在你自己的网站上插入这个,首先通过 运行 原始 svg-crowbar-2 识别所需 SVG 块的序号。这是在调用 getscreenshot(myplot) 时插入的数字。