EML*_*EML 13 html javascript 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">
<![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>
Run Code Online (Sandbox Code Playgroud)
我尝试了各种各样的东西.如果我这样做:
// 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);
}
Run Code Online (Sandbox Code Playgroud)
然后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>
Run Code Online (Sandbox Code Playgroud)
文件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>
Run Code Online (Sandbox Code Playgroud)
大概答案是将脚本放入标题?
Phr*_*ogz 23
一般来说,问题是双重的三倍:
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();
Run Code Online (Sandbox Code Playgroud)
请在此处查看: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 (/^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>
Run Code Online (Sandbox Code Playgroud)
请在此处查看:http://phrogz.net/SVG/import_svg_ie9.xhtml
编辑2:可疑,问题是onload动态添加脚本时事件不会触发.这是一个有效的配对解决方案:
onload事件处理程序.相反,信任document存在.svgRoot; 如果它不存在,请使用document.documentElement.svgRoot设置为新svg元素.这是代码的实际应用:
并且,如果我的网站关闭,这里是后代的代码:
脚本created.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>
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
27387 次 |
| 最近记录: |