2012-04-25 165 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解析器。