Javascript 如何将SVG图像动态插入HTML?
我有一些代码可以通过Ajax从服务器检索脚本svg图像。我可以将图像文本返回到浏览器中,但我找不到将其插入到实际显示它的DOM中的方法。有人能帮忙吗? svg如下所示:Javascript 如何将SVG图像动态插入HTML?,javascript,html,ajax,svg,Javascript,Html,Ajax,Svg,我有一些代码可以通过Ajax从服务器检索脚本svg图像。我可以将图像文本返回到浏览器中,但我找不到将其插入到实际显示它的DOM中的方法。有人能帮忙吗? svg如下所示: <svg id="chart" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="init(evt)"> <script type="application/ecmascript">
<svg id="chart" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="init(evt)">
<script type="application/ecmascript">
<![CDATA[
...lots of code, changes on each Ajax request
//]]>
</script>
<script type="application/ecmascript" xlink:href="js-on-server-1.js"/>
<script type="application/ecmascript" xlink:href="js-on-server-2.js"/>
</svg>
然后Opera和Chrome什么也不做,F/F抱怨“[object XMLDocument]”。如果我将“responseXML”更改为“responseText”,则Opera/Chrome会在正确的位置正确显示整个svg文本(而不是图像),而F/F仍会给出相同的警告。
我还尝试将响应分配给innerHTML,但这没有任何作用。
有什么想法吗?谢谢
编辑
为了回应下面的Phrogz'z回答,我添加了两个简单的svg文件。第一个是一个“标准”的简单svg,显示一个圆圈。第二个是脚本svg,显示一个矩形。除了IE8-,您应该能够在任何浏览器中直接查看两者。
如果我编辑Phrogz'z代码以使用圆形文件(将“stirling4.svg”替换为该文件的名称),那么它可以工作,但是如果我想要脚本化的矩形,它就不能工作。在F/F、Opera、Chromium上测试,但在(我的)Chromium上无论如何都不起作用
文件1,圆圈:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" />
</svg>
文件2,矩形:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="init(evt)">
<script type="application/ecmascript">
<![CDATA[
var svgDocument;
var svgns = "http://www.w3.org/2000/svg";
function init(evt) {
if(window.svgDocument == null)
svgDocument = evt.target.ownerDocument;
var lbox = svgDocument.createElementNS(svgns, "rect");
lbox.setAttributeNS(null, "x", 10);
lbox.setAttributeNS(null, "y", 10);
lbox.setAttributeNS(null, "width", 30);
lbox.setAttributeNS(null, "height", 30);
lbox.setAttributeNS(null, "stroke", "#8080ff");
lbox.setAttributeNS(null, "stroke-width", 2);
lbox.setAttributeNS(null, "fill-opacity", 0);
lbox.setAttributeNS(null, "stroke-opacity", 1);
lbox.setAttributeNS(null, "stroke-dasharray", 0);
svgDocument.documentElement.appendChild(lbox);
}
//]]>
</script>
</svg>
答案大概是将脚本放入标题中???一般来说,问题有两个方面:
responseXML
位于另一个DOM文档中,通常不能将节点从一个文档移动到另一个文档。应该使用将节点从一个文档导入到另一个文档onload
事件处理程序加载SVG文件不会通过创建节点或将其附加到文档中来调用这些处理程序。但是,script
块中的代码将被运行,因此您需要以一种独立工作的方式重写脚本,同时也可以使用动态加载下面是一个在Chrome、Safari和Firefox中工作的简单示例……但不是IE9:
var xhr=newxmlhttprequest;
open('get','stirling4.svg',true);
xhr.onreadystatechange=函数(){
如果(xhr.readyState!=4)返回;
var svg=xhr.responseXML.documentElement;
svg=document.importNode(svg,true);//在这些浏览器中是可选的
document.body.appendChild(svg);
};
xhr.send();
请在此处查看它的实际操作:
不幸的是,IE9不能正确支持
document.importNode
。为了解决这个问题,我们编写了自己的cloneToDoc
函数,通过递归地对层次结构进行爬网,为任何给定节点创建一个等效结构。下面是一个完整的工作示例:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head>
<meta http-equiv="content-type" content="application/xhtml+xml;charset=utf-8"/>
<title>Fetch and Include SVG in XHTML</title>
<script type="text/ecmascript"><![CDATA[
setTimeout(function(){
var xhr = new XMLHttpRequest;
xhr.open('get','stirling4.svg',true);
xhr.onreadystatechange = function(){
if (xhr.readyState != 4) return;
var svg = cloneToDoc(xhr.responseXML.documentElement);
document.body.appendChild(svg);
};
xhr.send();
},1000);
function cloneToDoc(node,doc){
if (!doc) doc=document;
var clone = doc.createElementNS(node.namespaceURI,node.nodeName);
for (var i=0,len=node.attributes.length;i<len;++i){
var a = node.attributes[i];
if (/^xmlns\b/.test(a.nodeName)) continue; // IE can't create these
clone.setAttributeNS(a.namespaceURI,a.nodeName,a.nodeValue);
}
for (var i=0,len=node.childNodes.length;i<len;++i){
var c = node.childNodes[i];
clone.insertBefore(
c.nodeType==1 ? cloneToDoc(c,doc) : doc.createTextNode(c.nodeValue),
null
); }
return clone;
}
]]></script>
</head><body></body></html>
使用脚本.xhtml导入svg
在XHTML中获取并包含脚本SVG
Try:addImage(xmlhttp.response,“某处”)代码>?html文档的哪种内容类型:text/html、application/xhtml+xml?您试图将SVG插入的documentElement的doctype和属性是什么?(1)测试页面最初没有文档或内容类型。我现在为XHTML1.0和XHTML1.1添加了doctype,没有任何更改。(2) 我还尝试了显式text/html和application/xhtml+xml,没有任何改变。(3) 我刚刚尝试了“xmlhttp.response”:F/F没有变化,但是Chrome&Opera现在说输出“未定义”,而不是svg文本。(4) 我正在将SVG插入一个空范围:。谢谢。我开始认为我需要将其理解为XML(responseXML)、importNode,然后是appendChild。我会在一段时间内尝试一下……这里有一个简单的例子。我将很快为您创建一个SVG到HTML示例。我无法在Chrome(8.0.552.237(70801)Ubuntu10.10)上运行这个程序-你确定在Chrome上可以吗?下一个问题更棘手——它不适用于脚本svg。我在我的原始帖子中添加了两个示例来替换您的“stirling4.svg”。谢谢。@user785194是的,这两个示例在Chrome v15中都能很好地工作。我将研究如何加载一个直接在脚本中创建内容的SVG。我假设问题是您正在使用onload
属性来触发脚本,而这不会触发。此外,当您说“我无法在Chromium上运行此功能”时,最好包含详细信息。会发生什么?您看到控制台中有任何错误吗?@Phrogz我们有没有可能得到关于这个答案的更新,因为它的浏览量相对较高,而且似乎过时了?@Zachsauier仅仅因为它旧了并不意味着它过时了。:)你会包括哪些新信息?请注意,堆栈溢出类似于wiki,并鼓励用户改进现有答案。
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head>
<meta http-equiv="content-type" content="application/xhtml+xml;charset=utf-8"/>
<title>Fetch and Include SVG in XHTML</title>
<script type="text/ecmascript"><![CDATA[
setTimeout(function(){
var xhr = new XMLHttpRequest;
xhr.open('get','stirling4.svg',true);
xhr.onreadystatechange = function(){
if (xhr.readyState != 4) return;
var svg = cloneToDoc(xhr.responseXML.documentElement);
document.body.appendChild(svg);
};
xhr.send();
},1000);
function cloneToDoc(node,doc){
if (!doc) doc=document;
var clone = doc.createElementNS(node.namespaceURI,node.nodeName);
for (var i=0,len=node.attributes.length;i<len;++i){
var a = node.attributes[i];
if (/^xmlns\b/.test(a.nodeName)) continue; // IE can't create these
clone.setAttributeNS(a.namespaceURI,a.nodeName,a.nodeValue);
}
for (var i=0,len=node.childNodes.length;i<len;++i){
var c = node.childNodes[i];
clone.insertBefore(
c.nodeType==1 ? cloneToDoc(c,doc) : doc.createTextNode(c.nodeValue),
null
); }
return clone;
}
]]></script>
</head><body></body></html>