2012-04-25 161 views
2

我相信我的问题的答案可以在Is there an equivalent of canvas's toDataURL method for SVG?中找到。有人可以确认或给我一个正确的方向指针。toDataURL不适用于具有SVG图像的html5画布

如果画布包含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> 

我甚至写了使用节点0.4.2和节点用帆布开罗库等效的程序,我和SVG图像使用canvas.toDataURL()时,得到了同样的结果。当使用node-canvas时,由于某种原因img.onload事件没有被触发,如果我试图在不等待onload事件的情况下绘制图像,那么我得到一个错误,说图像没有完成加载。节点程序也可以在下面找到。

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> 
+0

的[栅格化的在文档的SVG画布]可能重复(http://stackoverflow.com/questions/8158312/rasterizing-an-in-document-svg-to-canvas) – Phrogz 2012-04-25 14:43:32

+0

的Webkit目前玷污的当你画一个SVG的时候画布(由于难以跟踪的安全问题)。在FF v12之前,Firefox也是如此,但现在已经修复。如果您需要数据URL,您现在需要使用像CanVG这样的SVG解析器。 – Phrogz 2012-04-25 14:54:01

+0

谢谢@Phrogz。你的评论是我需要的。 – 2012-04-26 10:04:22

回答

0

的Webkit目前玷污画布当你画的SVG(由于难以跟踪的安全问题)。在FF v12之前,Firefox也是如此,但现在已经修复。如果您需要数据URL,您现在需要使用像CanVG这样的SVG解析器。