坎夫 |将 SVG 转换为 Canvas 以输出为图像

Posted

技术标签:

【中文标题】坎夫 |将 SVG 转换为 Canvas 以输出为图像【英文标题】:Canvg | Converting SVG to Canvas to output as image 【发布时间】:2015-12-02 16:14:19 【问题描述】:

我在 SVG 中有一个复杂的交互式图形。我想把 SVG 变成一个隐藏的画布,这样我就可以让用户输出为 png/pdf。

test111.js 在其中创建 div#forSVG 和 svg#svg(加上圆圈、路径、文本)。

<html>
    <head>
        <link rel="stylesheet" type="text/css" href="sql.css">
        <script type="text/javascript" src="d3.v3.js"></script> 


        <script type="text/javascript">
            function start() 

                var canvas = document.getElementById("canvas");

                var svg = document.getElementById("forSVG");
                var svgWider = svg.outerHTML;

                console.log(svg);

                canvg(canvas, svg);

            
        </script>           




    </head>
    <body onload="start()">
        <script type="text/javascript" src="test111.js"></script>

<script type="text/javascript" src="rgbcolor.js"></script> 
<script type="text/javascript" src="StackBlur.js"></script>
<script type="text/javascript" src="canvg.js"></script>


<canvas id="canvas"  ></canvas> 

</body>     

我尝试使用 svg#svg、div#forSVG 和 div.outerHTML 作为 canvg 函数的输入,但我经常收到错误消息,例如:

TypeError: undefined is not a function (evaluating 's.substr(0,1)')

有不同的错误,但它们都在 canvg.js 的第 50 行左右,我怀疑它们都与未定义的 s 变量有关。编辑 1640:canvg.js 的相关行告诉我们 s 是什么:

this.canvg = function (target, s, opts) 

所以当我调用 canvg(canvas, svg) 时,我认为 s 是我输入的 svg 变量(opts 是可选的)。 Console.logging (typeof svg) 返回 object

canvg.js 的前 60 行:

/*
 * canvg.js - Javascript SVG parser and renderer on Canvas
 * MIT Licensed
 * Gabe Lerner (gabelerner@gmail.com)
 * http://code.google.com/p/canvg/
 *
 * Requires: rgbcolor.js - http://www.phpied.com/rgb-color-parser-in-javascript/
 */
(function()
    // canvg(target, s)
    // empty parameters: replace all 'svg' elements on page with 'canvas' elements
    // target: canvas element or the id of a canvas element
    // s: svg string, url to svg file, or xml document
    // opts: optional hash of options
    //       ignoreMouse: true => ignore mouse events
    //       ignoreAnimation: true => ignore animations
    //       ignoreDimensions: true => does not try to resize canvas
    //       ignoreClear: true => does not clear canvas
    //       offsetX: int => draws at a x offset
    //       offsetY: int => draws at a y offset
    //       scaleWidth: int => scales horizontally to width
    //       scaleHeight: int => scales vertically to height
    //       renderCallback: function => will call the function after the first render is completed
    //       forceRedraw: function => will call the function on every frame, if it returns true, will redraw
    this.canvg = function (target, s, opts) 
        // no parameters
        if (target == null && s == null && opts == null) 
            var svgTags = document.querySelectorAll('svg');
            for (var i=0; i<svgTags.length; i++) 
                var svgTag = svgTags[i];
                var c = document.createElement('canvas');
                c.width = svgTag.clientWidth;
                c.height = svgTag.clientHeight;
                svgTag.parentNode.insertBefore(c, svgTag);
                svgTag.parentNode.removeChild(svgTag);
                var div = document.createElement('div');
                div.appendChild(svgTag);
                canvg(c, div.innerHTML);
            
            return;
        

        if (typeof target == 'string') 
            target = document.getElementById(target);
        

        // store class on canvas
        if (target.svg != null) target.svg.stop();
        var svg = build(opts || );
        // on i.e. 8 for flash canvas, we can't assign the property so check for it
        if (!(target.childNodes.length == 1 && target.childNodes[0].nodeName == 'OBJECT')) target.svg = svg;

        var ctx = target.getContext('2d');
        if (typeof(s.documentElement) != 'undefined') 
            // load from xml doc
            svg.loadXmlDoc(ctx, s);
        
        else if (s.substr(0,1) == '<') 
            // load from xml string
            svg.loadXml(ctx, s);
        
        else 
            // load from url
            svg.load(ctx, s);
        
    

编辑结束

谁能发现我做错了什么?变量 svg 找到动态创建的 div 和 svg 没有任何问题(它们正确地登录到控制台)。 谢谢

【问题讨论】:

如果问题出现在canvg.js:50左右,那么我建议发布canvg.js。当没有什么可看的时候,很难帮助诊断问题。 【参考方案1】:

感谢 TJ - 你的观点帮助我找到了正确的方向。

Canvg 似乎需要一个字符串或 html 输入,而不是一个对象。所以这行得通:

            var canvas = document.getElementById("canvas");

            var svg = document.getElementById("div#forSVG");
            var svgWider = svg.innerHTML;
            canvg(canvas, svgWider);

【讨论】:

您可以(并且应该)将自己的回复标记为解决方案,如果它帮助您解决了问题。这将标志着这个 SO 问题也为其他人解决了。【参考方案2】:

在我脑海中,我建议检查一下“s”是什么。它实际上可能不是一个字符串,因此执行“s.substr(0,1)”将是您的错误中引用的“未定义”。

【讨论】:

以上是关于坎夫 |将 SVG 转换为 Canvas 以输出为图像的主要内容,如果未能解决你的问题,请参考以下文章

如何将 SVG 文件转换为 HTML5 的画布?

将svg转换为png时如何包含CSS样式

以编程方式将 SVG 形状转换为路径(lineto、moveto)

如何使用 canvg.js 和 Canvas 将 SVG 导出为 PNG

H5中canvas和svg绘图方式介绍

回形针 - 将 SVG 转换为 PNG 时保持透明度