我有一些代码可以通过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"> <![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>
我尝试过各种东西。如果我这样做:
// xmlhttp.onreadystatechange: addImage(xmlhttp.responseXML, "somewhere"); ... function addImage(txt, dst_id) { var scr = document.createElement("div"); if("textContent" in scr) scr.textContent = txt; // everybody else else scr.text = txt; // IE document.getElementById(dst_id).appendChild(scr); }
然后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上进行了测试,但在(my)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>
大概答案是将脚本放入标头中?
通常,问题是 双重的 三重的:
HTML不是XHTML,在撰写本文时,HTML中对SVG的支持还很拙劣且定义不清。解决方案是使用真实的XHTML文档,其中SVG命名分隔的元素实际上被视为SVG。
该responseXML是另一个DOM文档,你不能通常只是从一个文档移动节点到另一个。您应该用来document.importNode将节点从一个文档导入到另一个文档。
responseXML
document.importNode
使用onload事件处理程序加载SVG文件不会通过创建节点或将其附加到文档来调用这些处理程序。script但是,该块中的代码将运行,因此您需要以独立的方式以及动态加载的方式重写脚本。
onload
script
这是一个适用于Chrome,Safari和Firefox的简单示例,但不适用于IE9:
var xhr = new XMLHttpRequest; xhr.open('get','stirling4.svg',true); xhr.onreadystatechange = function(){ if (xhr.readyState != 4) return; var svg = xhr.responseXML.documentElement; svg = document.importNode(svg,true); // surprisingly optional in these browsers document.body.appendChild(svg); }; xhr.send();
在此处查看其运行情况:http : //phrogz.net/SVG/import_svg.xhtml
不幸的是IE9无法正确支持document.importNode。为解决此问题,我们编写了自己的cloneToDoc函数,该函数通过递归爬网层次结构为任何给定节点创建等效结构。这是一个完整的工作示例:
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>
在此处查看其运行情况:http : //phrogz.net/SVG/import_svg_ie9.xhtml
编辑2: 令人怀疑的是,问题在于onload动态添加脚本时事件不会触发。这是一个有效的配对解决方案:
document
svgRoot
document.documentElement
svg
这是运行中的代码:
而且,如果我的网站出现故障,以下是后代代码:
脚本创建的.svg
<svg xmlns="http://www.w3.org/2000/svg"> <script type="text/javascript"><![CDATA[ function createOn( root, name, a ){ var el = document.createElementNS(svgNS,name); for (var n in a) if (a.hasOwnProperty(n)) el.setAttribute(n,a[n]); return root.appendChild(el); } // Trust someone else for the root, in case we're being // imported into another document if (!window.svgRoot) svgRoot=document.documentElement; var svgNS = svgRoot.namespaceURI; createOn(svgRoot,'rect',{ x:10, y:10, width:30, height:30, stroke:'#8080ff', "stroke-width":5, fill:"none" }); ]]></script> </svg>
import_svg_with_script.xhtml
<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 Scripted SVG in XHTML</title> <script type="text/ecmascript"><![CDATA[ setTimeout(function(){ var xhr = new XMLHttpRequest; xhr.open('get','script-created.svg',true); xhr.onreadystatechange = function(){ if (xhr.readyState != 4) return; var svg = xhr.responseXML.documentElement; svg = cloneToDoc(svg); window.svgRoot = svg; // For reference by scripts document.body.appendChild(svg); delete window.svgRoot; }; 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>