通常,问题是 双重的 三重的:
HTML不是XHTML,在撰写本文时,HTML中对SVG的支持还很拙劣且定义不清。解决方案是使用真实的XHTML文档,其中SVG命名分隔的元素实际上被视为SVG。
该
responseXML
是另一个DOM文档,你不能通常只是从一个文档移动节点到另一个。您应该用来document.importNode
将节点从一个文档导入到另一个文档。使用
onload
事件处理程序加载SVG文件不会通过创建节点或将其附加到文档来调用这些处理程序。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函数,该函数通过递归爬网层次结构为任何给定节点创建等效结构。这是一个完整的工作示例:
<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 (/^xmlnsb/.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动态添加脚本时事件不会触发。这是一个有效的配对解决方案:
- 重写脚本以删除
onload
事件处理程序。相反,document
存在的信任。 - 重写您的脚本以寻求全局
svgRoot
; 如果不存在,请使用document.documentElement
。 - 提取SVG时
svgRoot
,在将新svg
元素导入到文档中后将其设置为全局元素。
这是运行中的代码:
- 独立的脚本SVG:http://phrogz.net/SVG/script-created.svg
- 导入IE9的友好页面:http : //phrogz.net/SVG/import_svg_with_script.xhtml
而且,如果我的网站出现故障,以下是后代代码:
脚本创建的.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 (/^xmlnsb/.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>


