html - toDataURL 不适用于带有 SVG 图像的 html5 Canvas

标签 html node.js canvas webkit svg

我相信我的问题的答案可以在 Is there an equivalent of canvas's toDataURL method for SVG? 中找到.有人可以确认或给我一个正确方向的指示。

如果 Canvas 在 Chrome 和/或 Safari 上包含 SVG,我无法让 canvas.toDataURL() 生成正确的图像。下面的代码说明了这个问题。

<!DOCTYPE html>
<html>
<head>
  <script src="http://code.jquery.com/jquery-latest.js"></script>
  <script>
  $(document).ready(function () {
        var __readLocalXml = function(file)
        {
            xmlHttp = new XMLHttpRequest();
            xmlHttp.open("GET",file,false);
            xmlHttp.send();
            return xmlHttp.responseXML;
        };

        var __drawSVG = function(context, sourceSVG, x, y){
            var svg_xml = (new XMLSerializer()).serializeToString(sourceSVG);

            var img = new Image();
            img.src="";
            var myFunction = function() {
                context.drawImage(img, x, y);
            }
            img.addEventListener('load', myFunction, false);
            img.src = "data:image/svg+xml;base64,"+btoa(svg_xml);

        };

        var settings = {
            //White King
            //Chess_klt45.svg
            //<http://en.wikipedia.org/wiki/File:Chess_klt45.svg>
            'whiteKingSVG'      : function() { return __readLocalXml("svg/Chess_klt45.svg") }
        }

        var canvas = document.createElement('canvas');
        var cw = canvas.width = 45;
        var ch = canvas.height = 45;

        var context = canvas.getContext('2d');

        context.fillStyle = '#FFFFCC';
        context.fillRect(0,
                         0,
                        ch,
                        cw);
        __drawSVG(context, settings.whiteKingSVG(),0,0);

        $('#withCanvas').after(canvas);
        $('#withToDataUrl').after('<img src="' + canvas.toDataURL() + '" />');
  });
  </script>
</head>
<body>
    <h1>Works</h1>
    <div id="withCanvas"></div>
    <hr>
    <h1>Does not Work</h1>
    <div id="withToDataUrl"></div>
</body>
</html>

我什至使用 node 0.4.2 和使用 cairo 库的 node-canvas 编写了一个等效程序,当使用 canvas.toDataURL() 和 SVG 图像时我得到了相同的结果。当使用 node-canvas 时,由于某种原因没有触发 img.onload 事件,如果我试图在不等待 onload 事件的情况下绘制图像,我会收到一条错误消息,指出图像尚未完成加载。 Node 程序也可以在下面找到。

var Canvas = require('canvas');

var __readFileNodeSync=function(file){
   var fs = require('fs');

   try {
      return fs.readFileSync(file, 'ascii');
   } catch (err) {
      console.error("There was an error opening the file:");
      console.log(err);
   }
}

var __loadXml_xmldom=function(file){
   var DOMParser = require("xmldom").DOMParser;
   var xml=__readFileNodeSync(file)
   return new DOMParser().parseFromString(xml)
}

var __drawSVG = function(context, sourceSVG, x, y){
   var btoa = require('btoa');
   var XMLSerializer = require("xmldom").XMLSerializer;
   var svg_xml = new XMLSerializer().serializeToString(sourceSVG);
   var img = new Canvas.Image;
   img.onload = function(){
      context.drawImage(img, x, y);
   }
   img.src = "data:image/svg+xml;base64,"+btoa(svg_xml);
};


var settings = {
   //White King
   //Chess_klt45.svg
   //<http://en.wikipedia.org/wiki/File:Chess_klt45.svg>
   'whiteKingSVG'      : function() { return __loadXml_xmldom("../svg/Chess_klt45.svg") }
}

   var canvas = new Canvas();
   var cw = canvas.width = 45;
   var ch = canvas.height = 45;

   var context = canvas.getContext('2d');

   context.fillStyle = '#FFFFCC';
   context.fillRect(0,
                    0,
                   ch,
                   cw);
   __drawSVG(context, settings.whiteKingSVG(),0,0);

   console.log("<html>");
   console.log("<head>");
   console.log("</head>");
   console.log("<body>");
   console.log('<img src="'+canvas.toDataURL() + '" />');
   console.log("</body>");
   console.log("</html>");

编辑 感谢@Phrogz 的评论,我得以解决我的问题
下面是问题解决后的代码

<!DOCTYPE html>
<html>
<head>
  <script type="text/javascript" src="http://canvg.googlecode.com/svn/trunk/rgbcolor.js"></script> 
  <script type="text/javascript" src="http://canvg.googlecode.com/svn/trunk/canvg.js"></script>
  <script src="http://code.jquery.com/jquery-latest.js"></script>
  <script>
  $(document).ready(function () {

        var settings = {
            //White King
            //Chess_klt45.svg
            //<http://en.wikipedia.org/wiki/File:Chess_klt45.svg>
            'whiteKingSVG'      : "svg/Chess_klt45.svg" 
        }

        var canvas = document.createElement('canvas');

        var cw = canvas.width = 45;
        var ch = canvas.height = 45;
        var context = canvas.getContext('2d');

        context.fillStyle = '#FFFFCC';
        context.fillRect(0,
                     0,
                    ch,
                    cw);

        canvg(canvas, settings.whiteKingSVG, { 
                ignoreMouse: true, 
                ignoreAnimation: true, 
                ignoreDimensions: true, 
                ignoreClear: true, 
                offsetX: 0, 
                offsetY: 0
        });
        $('#withCanvas').after(canvas);
        $('#withToDataUrl').after('<img alt="whiteKing.png" src="' + canvas.toDataURL("image/png") + '" />');
  });
  </script>
</head>
<body>
    <h1>Works</h1>
    <div id="withCanvas"></div>
    <hr>
    <h1>Works! (using canvg)</h1>
    <div id="withToDataUrl"></div>
</body>
</html>

最佳答案

Webkit currently taints the canvas when you draw an SVG to it (due to difficult-to-track security concerns). Until FF v12 this was also the case with Firefox, but it is now fixed. You will need to use an SVG parser like CanVG for now if you need the data URL.

关于html - toDataURL 不适用于带有 SVG 图像的 html5 Canvas ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10317970/

相关文章:

node.js - 为什么我的 swig 模板无法在 MEAN Web 应用程序中呈现?

javascript - Node.js Socket.io ~ 连接时不起作用

javascript - SVG 和 CSS3 动画在 IE 和 Safari 中不起作用

html - chrome 中的 EaselJs 错误

javascript - 使用 Gulp + Browserify 时,对象 #<Readable> 没有方法 'write'

javascript - HTML5 和 Canvas/createImageData

javascript - HTML Canvas 游戏不显示

android - 如何在 View.DragShadowBuilder.onProvideShadowMetrics 中定位 Canvas

Java:Swing 中的 HTML,链接边距不起作用

javascript - AngularJS 没有更新?