【问题标题】:Convert very large SVG to PNG using <canvas>使用 <canvas> 将非常大的 SVG 转换为 PNG
【发布时间】:2015-11-20 17:52:47
【问题描述】:

我正在尝试将大型 SVG(它的数据 URL 大约为 750000 - 1000000 个字符)转换为 PNG,方法是将其数据 url 通过图像传递到画布中,但图像仅加载大约 1/4 SVG。

创建方式:

var svg_xml = (new XMLSerializer()).serializeToString(svg),
    url = 'data:image/svg+xml;base64,' + btoa(svg_xml);

var img = new Image();
img.width = 730;
img.height = 300;
img.onload = function(){
    var canvas = document.create('canvas');
    canvas.width = 730;
    canvas.height = 300;

    var ctx = canvas.getContext('2d');
    ctx.drawImage(img, 0, 0, 730, 300);

    callbackFn(canvas.toDataURL('image/png');
}
img.src = url

编辑

我尝试实现 canvg 来绘制 SVG,但 DataURL 产生的结果是空白图像:

var svg_xml = (new XMLSerializer()).serializeToString(svg);
var canvas = document.createElement('canvas');
canvas.width = 730;
canvas.height = 300;

var ctx = canvas.getContext('2d');
ctx.drawSvg(svg_xml, 0, 0, 730, 300);
callbackFn(canvas.toDataURL('image/png');

我用的方法有什么问题吗?

进一步编辑

我现在相当确信这是画布未能绘制整个图像,因为我尝试实施 Blob 解决方案以达到相同的效果:

var svg_xml = (new XMLSerializer()).serializeToString(svg),
    blob = new Blob([svg_xml], {type:'image/svg+xml;charset=utf-8'}),
    url = window.URL.createObjectURL(blob);

var img = new Image();
img.width = 730;
img.height = 300;
img.onload = function(){
    var canvas = document.create('canvas');
    canvas.width = 730;
    canvas.height = 300;

    var ctx = canvas.getContext('2d');
    ctx.drawImage(img, 0, 0, 730, 300);

    window.URL.revokeObjectURL(url);
    callbackFn(canvas.toDataURL('image/png');
}
img.src = url   

图像再次加载正常,转到 URL(在它被撤销之前)也能正常显示图像。

canvas dataURL 的长度不一致,所以我不认为这是最大化,有没有办法检测canvas 大小?该应用程序仅支持 Chrome 和 FireFox。

【问题讨论】:

  • 非常有趣,看起来应该可以工作...不确定 SVG 是否遵守宽度和高度规则(我倾向于在调整它们的大小时遇到​​一些 CSS 问题)但这应该可以工作。无关紧要,但是:您不应该调用图像构造函数(又名new Image() 而不是new Image)吗?
  • 写这篇文章时,这是一个错误类型......
  • @somethinghere new Imagenew Image() 都是有效的,如果你没有传递任何参数,你可以去掉括号
  • @spencerkillen 酷,我从没想过要省略括号。虽然两者都有效,但我的直觉喜欢括号,因为它们看起来像是执行了某些东西,而不是声明。但很高兴知道,谢谢!
  • @matts1189 SVG XML 中的宽度/高度设置是什么?即在此节点中:&lt;svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"&gt;

标签: javascript canvas svg


【解决方案1】:

Working fiddle.

HTML:

    <div>
        <svg xmlns="http://www.w3.org/2000/svg"
              width="526" height="233">
          <rect x="13" y="14" width="500" height="200" rx="50" ry="100"
              fill="none" stroke="blue" stroke-width="10" />
        </svg>
        <a id='imgId'>Save</a>
    </div>
    <canvas></canvas>

JavaScript:

var svg = document.getElementsByTagName('svg')[0];
var svg_xml = (new XMLSerializer()).serializeToString(svg),
    blob = new Blob([svg_xml], {type:'image/svg+xml;charset=utf-8'}),
    url = window.URL.createObjectURL(blob);

var img = new Image();
img.width = 730;
img.height = 300;
img.onload = function(){
    var canvas = document.createElement('canvas');
    canvas.width = 730;
    canvas.height = 300;

    var ctx = canvas.getContext('2d');
    ctx.drawImage(img, 0, 0, 730, 300);

    window.URL.revokeObjectURL(url);
    var canvasdata = canvas.toDataURL('image/png');
    var a = document.getElementById('imgId');
    a.download = "export_" + Date.now() + ".png";
    a.href=canvasdata;   
}
img.src = url

您的问题:

为什么图片只加载了 SVG 的 1/4?

答案:

请遵守以下规则:

  1. x&lt;rect/&gt; + width&lt;rect/&gt; width 的 &lt;svg/&gt;
  2. y &lt;rect/&gt; + height &lt;rect/&gt; height &lt;svg/&gt;

例如:

<svg xmlns="http://www.w3.org/2000/svg" width="500" height="200">
     <rect x="10" y="10" width="550" height="250" rx="50" ry="100"
                  fill="none" stroke="blue" stroke-width="10" />
</svg>

这里,&lt;rect/&gt;x = 10&lt;rect/&gt; 的宽度 = 550&lt;svg&gt; 的宽度 = 500

所以,10+550>500

在这种情况下,图像将被部分渲染。

希望这能解决您的问题。

【讨论】:

  • 但是那样的话,渲染的原始svg不会也被裁剪掉吗?
  • 检查我的小提琴并更改xwidth的值.....它将帮助您可视化结果。
  • 如果我注意到该评论,请注意我不是 OP。我也无权访问犯罪 svg 文件,我在 2 个月前提出了要求。现在对于您的答案的评论,我提出了一个问题,但它实际上是一个修辞问题。我知道,如果您的假设是正确的,那么图像将不会“加载正常并且转到 URL(在它被撤销之前)也会很好地显示图像。”在画布上绘制时,它将被裁剪。 small example using your fiddle
猜你喜欢
  • 2018-03-17
  • 2015-11-14
  • 2015-10-04
  • 2015-04-06
  • 1970-01-01
  • 2021-05-31
  • 2016-07-22
  • 2016-07-14
  • 2018-09-07
相关资源
最近更新 更多