如何从复杂的svg正确生成画布

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何从复杂的svg正确生成画布相关的知识,希望对你有一定的参考价值。

我试图从我的网站导出一个复杂的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);
}

这是网页上显示的一排卡片:Cards row

右边的情节是我正在关注我的试验,以及正在完成未编辑的那个。使用canvg.js查看使用html2canvas,jsPDF等产生的结果与fiddle with SVG pasted中出现的相同误解结果

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

干杯!

答案

你可以用迈克博斯托克(或者也许是纽约时报)的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,但也有一些,所以我不会发布链接。谷歌搜索应该找到你需要的东西。

如果你想以编程方式完成所有这些,那就是另一个故事。

更新: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源;
  • 单个图下载接收SVG序列号;
  • 下载后重新加载页面。

更改可以在js文件中找到singledownload-svg-crowbar-2.js at: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文件名,并调用单个SVG下载器函数singleSVGcrowbar,在singledownload-svg-crowbar-2.js上定义:

<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正确生成画布的主要内容,如果未能解决你的问题,请参考以下文章

在将 svg 转换为 img 中使用 css

画布上的模糊 svg

如何使用createjs和animate cc在画布上移动svg图形

生成和拖动 SVG 元素 - 方法

使SVG linearGradient遵循路径

d3.js:将 SVG 地理路径转换为画布