对于SVG,是否有相当于canvas的toDataURL方法?

时间:2010-07-03 22:27:04

标签: javascript html5 canvas svg

我正在尝试将svg图像加载到画布中以进行像素操作 对于svg

,我需要toDataURLgetImageData等方法 Chrome浏览器上的

我可以尝试通过图片和画布

var img = new Image()
img.onload = function(){
  ctx.drawImage(img,0,0) //this correctly draws the svg image to the canvas! however...
  var dataURL = canvas.toDataURL(); //SECURITY_ERR: DOM Exception 18
  var data = ctx.getImageData(0,0,img.width, img.height).data //also SECURITY_ERR: DOM Exception 18
  }
  img.src = "image.svg" //that is an svg file. (same domain as html file :))

但是我遇到了安全错误。 还有别的吗?

以下是问题http://clstff.appspot.com/gist/462846的实时演示(您可以查看来源)

5 个答案:

答案 0 :(得分:8)

var dataUrl = 'data:image/svg+xml,'+encodeURIComponent(svgString);

答案 1 :(得分:5)

来自:http://www.svgopen.org/2009/papers/12-Using_Canvas_in_SVG/#d4e105

  

您无法使用SVG的原因   图像元素作为源的   drawImage方法很简单,但是   痛苦:当前的画布   规范(尚未)允许   引用SVGImageElement作为源   对于drawImage而言只能应付   HTMLImageElement,HTMLCanvasElement   和HTMLVideoelement。这个   希望是短暂的到来   在此过程中解决   定义“HTML5中的SVG”行为和   可以扩展到允许   SVGSVGElement也是如此。 xhtml:img   清单3中的元素使用   可见性:隐藏,因为我们不想要它   干扰其可见副本   画布。

答案 2 :(得分:1)

是的,你不能直接这样做,但你可以使用canvg,我的意思是,将SVG绘制到Canvas,并从Canvas获取数据网址。它不是没有错误,特别是对于复杂的渐变处理,但我有一些积极的经验。

答案 3 :(得分:1)

首先下载一个js库svg_todataurl.js并将其包含在内

然后只需粘贴此代码

var SVGtopngDataURL = document.getElementById("svg_element_id").toDataURL("image/png");

答案 4 :(得分:0)

用代码说明Hubert OG的答案;首先有2条评论。

首先(谢谢罗伯特·朗森(Robert Longson),它可能在没有encodeURIComponent的情况下也可以工作,但是最好包括它(例如,如果您有类似fill="url(#pattern)"之类的编码URIComponent,则必须使用#字符)

第二,SVG名称空间不是不是可选的,但是它可能不包含在svgElt.outerHTML中。特别是,如果您是通过createElementNS创建的svg节点,就像这样

svgElt = document.createElementNS("http://www.w3.org/2000/svg", 'svg')

然后随后对svgElt.outerHTML 的调用将不会包含名称空间属性,除非您稍后以某种方式包括名称空间属性,否则这将导致代码无法正常工作

var imgEnc    = new Image();
var imgEncNS  = new Image();
var prefix    = 'data:image/svg+xml,';
var svgOpen   = '<svg width="200" height="30">';
var svgClose  = '</svg>';
var svgOpenNS = '<svg xmlns="http://www.w3.org/2000/svg" width="200" height="30">';
var rect      = '<rect width="200" height="30" fill="black"/>';
var html      = svgOpen + rect + svgClose;
var htmlNS    = svgOpenNS + rect + svgClose;
var htmlEnc   = window.encodeURIComponent(html);
var htmlEncNS = window.encodeURIComponent(htmlNS);
imgEnc.src   = prefix + htmlEnc;
imgEncNS.src = prefix + htmlEncNS;
function T(txt){
  document.body.appendChild(document.createTextNode(txt));
}
function HR(){ document.body.appendChild(document.createElement('hr')); }
function BR(){ document.body.appendChild(document.createElement('br')); }
function A(arg){ document.body.appendChild(arg); }
T('without namespace'); BR(); A(imgEnc); HR();
T('with namespace'); BR(); A(imgEncNS);

您可以在我对this question的回答中使用函数outerXHTML来解决缺少的名称空间问题

或这样

function imgFromSVGnode(node){
    function setNS(elt, parentNS){
        var namespace = elt.namespaceURI;
        if (namespace!==parentNS){
            elt.setAttribute('xmlns', namespace);
        }
        for (var i=0; i<elt.childNodes.length; i++){
            setNS(elt.childNodes[i], namespace);
        }
    }
    setNS(node, null);
    var html = node.outerHTML;
    var dataURL = 'data:image/svg+xml,' + window.encodeURIComponent(html);
    var img = new Image();
    img.src = dataURL;
    return img;
};