【问题标题】:Jquery: convert SVG to PNG with new sizeJquery:将 SVG 转换为具有新大小的 PNG
【发布时间】:2015-12-16 13:12:27
【问题描述】:

我正在使用以下函数将 SVG 转换为 PNG 并提供下载:

<svg id="chart">
    ...some contenthere
</svg>

function() {
        var svg = $("#chart")[0],
            bBox = $('#chart')[0].getBBox();

        var width = bBox.width*2,
            height = bBox.height*2;

        var canvas = $("canvas")[0],
            serializer = new XMLSerializer(),
            svgString = serializer.serializeToString(svg);

        canvas.width = width;
        canvas.height = height;

        canvg(canvas, svgString);

        var dataURL = canvas.toDataURL('image/png'),
            data = atob(dataURL.substring('data:image/png;base64,'.length));

        asArray = new Uint8Array(data.length);

        for (var i = 0; i < data.length; ++i) {
            asArray[i] = data.charCodeAt(i); 
            } 

        var blob = new Blob([asArray.buffer], {type: 'image/png'}); 
        saveAs(blob, 'climatechart.png'); 
}

它实际上工作正常,尽管输出图像与浏览器中的 SVG 大小相同。如何为图像设置新尺寸?我也尝试直接从 svg 而不是 BBox 获取大小,但它是一样的。

【问题讨论】:

  • 只需创建第二个具有所需大小的画布并使用secondContext.drawImage(firstCanvas, 0, 0, outputWidth, outputHeight),这会将您的图像缩小到该画布的大小。然后做你已经在做的事情。

标签: javascript jquery svg canvg


【解决方案1】:

此解决方案基于远程格式化服务器而不是本地代码。它使用 XSL FO 服务器端直接将 SVG 渲染为位图,允许您设置分辨率以获得高质量输出。

文档:http://www.cloudformatter.com/CSS2Pdf.APIDoc.Usage

示例:http://jsfiddle.net/g75t4oyq/

在 div 中来自 SVG 的 JPG 格式 @ 300dpi 的代码实现:

click="return xepOnline.Formatter.Format('JSFiddle', {render:'newwin', mimeType:'image/jpg', resolution:'300', srctype:'svg'})";
jQuery('#buttons').append('<button onclick="'+ click +'">JPG @300dpi</button>');

【讨论】:

    【解决方案2】:

    您可以轻松地调整画布的大小,因为您可以将其绘制为 画布。以下示例忽略了任何 SVG 渲染,根据您的问题可以正常工作,但它确实展示了如何使用另一个画布轻松调整画布的大小:

    var myCanvas = document.createElement('canvas');
    var myCtx    = myCanvas.getContext('2d');
        myCanvas.width = 200;
        myCanvas.height = 200;
        myCtx.arc(100, 100, 100, 0, Math.PI * 2, true);
        myCtx.fill();
    
    var seCanvas = document.createElement('canvas');
    var seCtx    = seCanvas.getContext('2d');
        seCanvas.width = 200;
        seCanvas.height = 200;
        seCtx.drawImage(myCanvas, 0, 0, 100, 100);
    
    document.body.appendChild(myCanvas);
    document.body.appendChild(seCanvas);

    之后,您可以使用这个新画布继续该过程。

    【讨论】:

    • 此解决方案的警告是,在放大原始图像时会降低质量。
    • @Kaiido 当然,是的。您在这里转换像素 - 它是一个画布。
    • 但是ctx.drawImage(svgImg) 会绘制一个 svg 图像,即矢量图像,所以有一种方法可以不丢失这种质量。无论如何,我正在将自己的 svg 写入位图脚本,并且永远不会退回到 canvg,因为它有很多不足之处:-)
    • 其实是的,我从来没有真正想过它,但drawImage 可以给它写一个 svg ......嗯......无论如何,我发布了这个作为一种方式调整图像大小,仅此而已。
    【解决方案3】:

    如果 svg 元素根据其大小定义了 viewBox 属性,则可以通过 height 和 width 属性调整 SVG 文档的大小;例如

    <svg width="500" height="200" viewBox="0 0 50 20" >
    

    viewBox 设置好后,画布中 svg 的缩放将按照您的编码进行。

    【讨论】:

    • 我忘了说我已经尝试过了。当画布显示在页面上时,它会正确放大画布。但是下载的版本不知何故被“裁剪”了,这意味着它只下载了整个画布的一个子集(左上角的矩形)。我是否必须在其他地方设置大小,例如在 blob 中?
    • 没错,画布的宽度/高度是 svg 大小的两倍,但图像本身的大小仍然相同。
    • 但是有没有办法同时调整该图像的大小?它的大小与我页面上的原始 SVG 相同,所以我只是想知道它从哪里获得大小信息。
    • 由于 svg 内联在您的 dom 节点中,因此您需要在将其渲染到画布之前对其进行缩放。为此,典型的解决方案是使用 svg 元素的 viewBox 属性,然后使用 height 和 width 属性进行缩放。
    【解决方案4】:

    好的,感谢您的建议,我终于找到了一个完美的解决方案(根据 Cédric Hartlands 的提示)。 viewbox 属性是我的代码中完全缺失的部分。 viewbox 定义如下:

    viewbox = "x y width height"
    

    因此,要放大&lt;svg&gt; 和其中的所有元素,有必要确保视图框的widthheight&lt;svg&gt; 元素的新宽度和高度完全匹配:

    //original version
    <svg> width="100" height="100" viewbox="0 0 100 100" preserveAspectRatio="xMinYMin meet"</svg>
    
    //scaled up version
    <svg> width="200" height="200" viewbox="0 0 200 200" preserveAspectRatio="xMinYMin meet"</svg>
    

    如果我将放大的svg 转换为canvas,它会适合整个图像而不会失去任何质量(无论如何这是矢量图的最大好处)。不敢相信我花了这么长时间才得到它。

    【讨论】:

      猜你喜欢
      • 2013-08-14
      • 2019-05-30
      • 2015-02-16
      • 2018-09-07
      • 1970-01-01
      • 2011-11-18
      • 2015-11-20
      • 2014-03-03
      • 2011-09-09
      相关资源
      最近更新 更多