将修改后的SVG绘制到画布上

3

我想要加载一个SVG图片,对其进行一些操纵,然后将其绘制到画布上。

这里有一个很好的示例,可以将SVG绘制到画布上:http://www.phrogz.net/tmp/canvas_from_svg.html

但是在这个示例中,SVG被创建为一个new Image('url.svg')对象。当你以这种方式创建SVG时,不幸的是似乎没有一个contentDocument来操作。只有当你将SVG创建为一个<object>元素时才会有一个contentDocument。

但是当我将SVG创建为一个对象,获取SVG的DOM节点并将其传递给context.drawImage(svgNode, x, y)时,在Firefox上它会抛出错误"Value could not be converted to any of: HTMLImageElement, HTMLCanvasElement, HTMLVideoElement."

看起来我要么找到一种方法将对象-SVG转换为HTMLImageElement,要么找到一种方法获取以图像形式加载的SVG的content document。是否有人知道如何做到这两点?或者是否有我所错过的第三种方法?


1
也许可以将SVG的内容文档转换为ObjectURL,并像此示例中那样使用它来创建图像:https://developer.mozilla.org/en-US/docs/HTML/Canvas/Drawing_DOM_objects_into_a_canvas - Philipp
2个回答

2
我成功地完成了它。诀窍在于:
  1. 使用XMLHttpRequest()将SVG作为XML文档加载
  2. 操作该XML文档
  3. 将XML文档转换为字符串
  4. 从该字符串创建一个ObjectURL
  5. 用该ObjectURL创建一个图像
  6. 将该图像复制到画布上
这是我的源代码: 编辑:不幸的是,它只在Firefox和Chrome中运行。在IE9中失败,因为不支持XMLSerializer()(它还不支持XML文档上的getElementById,但有解决方法),在Opera中失败,因为不支持createObjectUrl。
var xhr = new XMLHttpRequest();
xhr.onload = function() {
    // get the XML tree of the SVG
    var svgAsXml = xhr.responseXML;
    // do some modifications to the XML tree
    var element = svgAsXml.getElementById('hat');
    element.style.fill = '#ffff00';
    // convert the XML tree to a string
    var svgAsString = new XMLSerializer().serializeToString(svgAsXml);
    // create a new image with the svg string as an ObjectUrl
    var svgBlob = new Blob([svgAsString], {type: "image/svg+xml;charset=utf-8"});
    var url = window.URL.createObjectURL(svgBlob);
    var img = new Image();
    img.src = url;
    // copy it to the canvas
    img.onload = function() {
        var theCanvas = document.getElementById('theCanvas');
        var context = theCanvas.getContext('2d');
        context.drawImage(img, 0, 0);
        window.URL.revokeObjectURL(svgBlob);
    }
}
xhr.open("GET", "test.svg");
xhr.responseType = "document";
xhr.send();

1
将SVG的XML内容转换为字符串数据,然后制作成数据URI。您应该能够将其加载为图像。类似于这样:
new Image("data:image/svg+xml," + svgdata);

现在你应该能够将它绘制到画布上了。

抱歉,但这比说起来容易做起来难。正如我所说,我正在使用contentDocument修改SVG内容。这意味着我无法将SVG源代码作为XML字符串加载。而且SVG对象没有toDataUrl方法。这意味着要将SVG内容转换为XML字符串,我必须手动遍历整个SVG文档树并从中构建有效的XML。 - Philipp
你给了我一个想法。也许我可以将SVG作为通用的XMLDocument加载,并将其作为XML树而不是SVG对象进行操作。 - Philipp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接