Javascript不工作时SVG的动态修改

Javascript不工作时SVG的动态修改,javascript,html,svg,Javascript,Html,Svg,我试图动态修改嵌入html页面中的SVG文档,以便在发生某些事件(例如,按下按钮)时添加装饰程序 为此,我首先在“onload”期间将decorator图像插入SVG的“defs”元素,然后在事件发生期间将“use”元素添加到SVG组中。代码似乎(在Firefox中)在onload期间添加了image元素,在事件发生时添加了use元素,但没有显示装饰器图像。如果我坚持使用相同的SVG文档,所有浏览器都会正确显示它 让我给你看一个简化的代码。感谢Phrogz,这里有一个JSFIDLE: 想象一下这

我试图动态修改嵌入html页面中的SVG文档,以便在发生某些事件(例如,按下按钮)时添加装饰程序

为此,我首先在“onload”期间将decorator图像插入SVG的“defs”元素,然后在事件发生期间将“use”元素添加到SVG组中。代码似乎(在Firefox中)在onload期间添加了image元素,在事件发生时添加了use元素,但没有显示装饰器图像。如果我坚持使用相同的SVG文档,所有浏览器都会正确显示它

让我给你看一个简化的代码。感谢Phrogz,这里有一个JSFIDLE:

想象一下这个html页面:

 <!DOCTYPE html>
 <html>
 <head>
  <title>Dynamic Modification of SVG demo</title>
  <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
  <script language="javascript">
   var svgns = "http://www.w3.org/2000/svg";
   function setOnLoad()
   {
    var svg = document.getElementById("SVG_IMAGE").contentDocument;
    defs = svg.getElementsByTagName("defs");
    def1 = defs[0];
    var imageNote = document.SVG_IMAGE.contentDocument.createElementNS(svgns,"image");
    imageNote.setAttribute("width","22");
    imageNote.setAttribute("height","22");
    imageNote.setAttribute("id","noteImage");
     imageNote.setAttribute("xlink:href","data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAaFJREFUOI2lk79LW1EUxz/vKZ1i4G2BZBI6FeLWdswQEnS3tDgZcFXI3xHFOrh0cElpKbg+EArJIhZBeEo6CU4vkC0Yn6nGvvd18OaZ99IM0guH++Pc7+cezjnXksT/jPn0wa/f59r52efookvg9wDIFHJUi3nqZYf3b5ashEBSbPvusexKQ6u7Lbmer8HNra4Ht3I9X6u7LdmVhvbdY01qEuJsrSnX8xVG0jCUsrWmsrWmhqEURZLr+crWmgkIkjjpeLIrjYQ4DRiGUmggdqWhk44nSViS+PC5LYBvmyVGEzl9ZTG1B/i01wbgx1bJmgc4uujyfbNENHE5t/E1Xve+rD3ly+zXS6/5aCA2QOD3eLvoIGDOlGYsSib8yd4tOnGFEmVUao5GD8iEPQdEKX8cQaaQ4/SqH78wvvD37p7wzz2WEY99p1d9MoXcM6BazHPQvpwKZTQIGA0CIiOU8R20L6kW88+Aetnh0D2j1ekSmdcyy9sxb2FlGwyk1ely6J5RLzvjxEw3UvCgf9rMRprVypPCWa1spX/jSz/TFOCl4xHBR4DBDtGdcgAAAABJRU5ErkJggg==");
     def1.appendChild(imageNote);
    };

    function decorateSVG() {
     var svg = document.getElementById("SVG_IMAGE");
     var dElement = svg.contentDocument.getElementById("group1");
 var useNote = svg.contentDocument.createElementNS(svgns,"use");
 useNote.setAttribute("x","150");
 useNote.setAttribute("y","150");
 useNote.setAttribute("xlink:href","#noteImage");
 dElement.appendChild(useNote);
    };
   </script>
 </head>
 <body>
   <h1>Dynamic Modification of SVG demo - embed svg file with SVG image</h1>
   <p> A  yellow circle that was embeded using the svg "object" tag</p>
    <object id="SVG_IMAGE" preserveAspectRatio="xMidYMid meet"  data="basic_shapes_circle1.svg" width="400" y="0" x="0" type="image/svg+xml" onload="setOnLoad()">
    </object>
   <p>
    <button onclick="decorateSVG('circle')">Decorate circle </button>
   </p>
  <hr>
 </body>
</html> 

SVG演示的动态修改
var svgns=”http://www.w3.org/2000/svg";
函数setOnLoad()
{
var svg=document.getElementById(“svg_图像”).contentDocument;
defs=svg.getElementsByTagName(“defs”);
def1=defs[0];
var imageNote=document.SVG_IMAGE.contentDocument.createElements(svgns,“IMAGE”);
设置属性(“宽度”、“22”);
imageNote.setAttribute(“高度”、“22”);
setAttribute(“id”、“noteImage”);
imageNote.setAttribute(“xlink:href”,"数据:图像/png;Bas64,IBoBorWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+crWmgkIkjj4.关于这一问题的答案是:4.关于这一问题的答案是:4.关于这一问题的答案是:关于这一问题的答案是一个关于这一问题的研究。4.关于这一问题的答案是:4 4.关于这一问题的答案是:4 4.关于这一问题的答案是:4 4.关于这一问题的答案是:4 4.关于这一问题的答案是一个研究。4 4 4.关于这一问题的答案是,4 4.关于关于这一问题的答案是,4 4 4.关于一个关于关于关于关于关于关于关于这一问题的问题的答案的研究,他们的答案是一个问题的答案是,4 4。4 4。关于关于关于关于关于关于关于关于关于关于关于一个问题的问题的答案的答案的研究。4 4 4 4。关于关于关于关于关于关于关于关于关于关于关于关于一个研究的研究的问题的问题的答案的研究。4 4 4 4 4 4。关于关于关于关于关于关于关于关于关于关于关于关于gg==”;
def1.追加子项(imageNote);
};
函数decorateSVG(){
var svg=document.getElementById(“svg_图像”);
var dElement=svg.contentDocument.getElementById(“group1”);
var useNote=svg.contentDocument.createElements(svgns,“use”);
useNote.setAttribute(“x”、“150”);
useNote.setAttribute(“y”、“150”);
setAttribute(“xlink:href”,“#noteImage”);
删除。追加子项(使用注释);
};
SVG演示的动态修改-用SVG图像嵌入SVG文件
使用svg“object”标记嵌入的黄色圆圈

装饰圈


以及以下svg文档:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
 <defs>
  <!-- A circle of radius 200 -->
  <circle id="s1" cx="200" cy="200" r="200" fill="yellow" stroke="black" stroke-width="3"/>
 </defs>
 <g id="group1">
    <use x="0" y="0" xlink:href="#s1"/>
 </g>
</svg>

代码(假定)的结果如下:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
 <defs>
  <!-- A circle of radius 200 -->
  <circle id="s1" cx="200" cy="200" r="200" fill="yellow" stroke="black" stroke-width="3"/>
  <image width="22" height="22" id="noteImage" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAaFJREFUOI2lk79LW1EUxz/vKZ1i4G2BZBI6FeLWdswQEnS3tDgZcFXI3xHFOrh0cElpKbg+EArJIhZBeEo6CU4vkC0Yn6nGvvd18OaZ99IM0guH++Pc7+cezjnXksT/jPn0wa/f59r52efookvg9wDIFHJUi3nqZYf3b5ashEBSbPvusexKQ6u7Lbmer8HNra4Ht3I9X6u7LdmVhvbdY01qEuJsrSnX8xVG0jCUsrWmsrWmhqEURZLr+crWmgkIkjjpeLIrjYQ4DRiGUmggdqWhk44nSViS+PC5LYBvmyVGEzl9ZTG1B/i01wbgx1bJmgc4uujyfbNENHE5t/E1Xve+rD3ly+zXS6/5aCA2QOD3eLvoIGDOlGYsSib8yd4tOnGFEmVUao5GD8iEPQdEKX8cQaaQ4/SqH78wvvD37p7wzz2WEY99p1d9MoXcM6BazHPQvpwKZTQIGA0CIiOU8R20L6kW88+Aetnh0D2j1ekSmdcyy9sxb2FlGwyk1ely6J5RLzvjxEw3UvCgf9rMRprVypPCWa1spX/jSz/TFOCl4xHBR4DBDtGdcgAAAABJRU5ErkJggg=="/>
</defs>
<g id="group1">
  <use x="0" y="0" xlink:href="#s1"/>
  <use x="150" y="150" xlink:href="#noteImage"/>
 </g>
</svg>

如果将SVG文档保存到文件中,它将在任何浏览器中正确显示。 然而,当在内存中修改时,它似乎不起作用,我也不明白为什么。 有什么想法吗


提前感谢您的帮助。

问题在于您没有正确设置
xlink:href
属性。您正在执行以下操作:

someElement.setAttribute( "xlink:href", "…" );
这样做将创建一个名为“xlink:href”(无效名称)的属性,该属性没有名称空间。相反,您希望使用:

someElement.setAttributeNS( "http://www.w3.org/1999/xlink", "href", "…");
下面是一个正在运行的演示,展示了无论您是将动态创建的图像直接添加到组中,还是将其放置在
部分并通过
引用它,这都是有效的:

演示:
顺便说一句,为了方便和节省手腕,我建议您使用以下功能:

function createOn( dad, name, attrs, text ){
  var svg = dad.ownerSVGElement, doc = dad.ownerDocument;
  var ns = createOn.$NAMESPACES;
  var defaultNS = svg.namespaceURI;
  if (!ns){
    ns = createOn.$NAMESPACES = {};
    for (var a=svg.attributes,i=a.length;i--;) if (a[i].prefix=='xmlns') ns[a[i].localName] = a[i].nodeValue;
  }
  var p = name.split(':');
  var el = p[1] ? doc.createElementNS(ns[p[0]],p[1]) : doc.createElementNS(defaultNS,name);
  for (var a in attrs){
    p = a.split(':');
    if (p[1]) el.setAttributeNS(ns[p[0]],p[1],attrs[a]);
    else      el.setAttributeNS(null,a,attrs[a]);
  }
  if (text) el.appendChild(doc.createTextNode(text));
  return dad.appendChild(el);
}
像这样使用它:

var defs = svgDoc.querySelector('defs');
var img  = createOn(defs,'image',{
  x:100, y:150,
  width:22, height:22,
  id:'noteImage', 'xlink:href':data
});
它将自动查找元素名或属性名的名称空间前缀,只要前缀与所属文档上声明的名称空间匹配。下面是使用该前缀的更新演示:


演示:这里有一个简化的JSFIDLE,显示了这个问题:太好了,谢谢!很抱歉!Phrogz,你搞定了。非常感谢!