6

我正在尝试从我的网站将复杂的 SVG 块(使用 c3 生成)导出为图像(无论是 png、svg、pdf,此时我对任何解决它的方法都持开放态度,尽管矢量格式是理想的) . 我尝试过 html2canvas、canvg、jsPDF 以及该帮派的所有酷孩子。问题是:我的一个情节都搞砸了。线变成了区域,区域被反转了,颜色被破坏了,......你的名字。

我离成为 js 专家还差得很远。我刚到这里,我正在寻找我的路,有些人请多多包涵。

我不知道这是 CSS 问题还是什么。是的,我们在 html 后面确实有 CSS。

我的临时解决方案是使用 jQuery.print.js 来调用我的 div 的打印。由于许多原因,这远非理想:

  • 没有bbox。它生成由用户定义的页面大小的 PDF,而不是图像大小;

  • 我正在使用具有自动调整大小的引导卡。每当按下“打印图像”时,打印都会使用当前尺寸。我已经尝试隐藏卡片来重新调整目标卡片的大小,但是调整大小只会在打印调用之后发生,原因我不知道。如果这个问题解决了,这个临时解决方案会更好,虽然仍然是临时的。

所以,一个问题是:

  • 如何获得如图所示的 SVG?
  • 或者,如何在调用打印之前调整卡片的大小?
  • 或者,如何在没有从 canvg/jsPDF 获得的格式错误的情况下生成栅格(png/jpeg)?

现在执行打印调用的函数是:

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);
}

这是网页上显示的卡片行: 卡片行

右边的情节是我正在集中尝试的情节,也是正在完成未格式化的情节。检查使用 html2canvas、jsPDF 等产生的结果与使用 canvg.js使用 SVG pasteed 时出现的错误构造相同

PS:是的,我确实搜索了很多。这就是我最终尝试 html2canvas、canvg、jsPDF、jqprint 的方式...

干杯!

4

2 回答 2

1

您可以使用 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图像。然后选择您想要的输出尺寸。然后单击导出。 这个网站有一步一步的如何做到这一点

也有在线将 SVG 转换为 PNG 的网站,但是有一些,所以我不会发布链接。谷歌搜索应该找到你需要的东西。

如果您想以编程方式完成所有这些工作,那就另当别论了。

更新:SVG Crowbar(1 和 2)仅适用于 chrome。

于 2018-06-08T16:12:23.757 回答
1

最终结果使用了@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-撬棍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) 调用中插入的数字。

于 2018-06-14T14:03:38.533 回答