SVG / XML中有一些innerHTMLreplace吗?
在HTML中,我可以通过提供一个stringforms的模板来构build一个简单的模板系统,replace它的一些部分,然后使用innerHTML
将其分配给某个容器。
var templ = '<span>{myText}</span>' var newContent = templ.replace( '{myText}', someVariable ); document.querySelector( '#myContainer' ).innerHTML = newContent;
这样我可以利用浏览器的HTMLparsing器,而不必重复使用document.createElement()
。 如果模板增长超过几个元素,后者可能非常麻烦。
然而,在SVG中,作为innerHTML
的元素,甚至innerSVG
都没有这个属性。
所以我的问题是: 有没有什么我可以在SVG中使用ro类似于上面的例子的方法,或者我坚持document.createElement()
(或者respectivly一些使用它的lib)?
与我的问题一样:Vanilla JavaScript解决scheme是首选,但任何指向提供解决scheme的lib指针表示赞赏。
您可以使用DOMParser来parsingXML: https : //developer.mozilla.org/en/Parsing_and_serializing_XML然后,您可以使用importNode将它存入您的现有文档中: https : //developer.mozilla.org/en/DOM /document.importNode结束了这样的事情…
var doc = new DOMParser().parseFromString( '<svg xmlns="http://www.w3.org/2000/svg"><circle cx="100" cy="100" r="20"/></svg>', 'application/xml'); someElement.appendChild( someElement.ownerDocument.importNode(doc.documentElement, true));
我的innerSVG垫片怎么样? CoffeeScript源代码如下,编译好的JavaScript文件位于https://gist.github.com/2648095
# Important: You must serve your pages as XHTML for this shim to work, # otherwise namespaced attributes and elements will get messed up. Object.defineProperty SVGElement.prototype, 'innerHTML', get: () -> $temp = document.createElement 'div' $node = @cloneNode true for $child in $node.children $temp.appendChild $child return $temp.innerHTML set: (markup) -> while @firstChild @firstChild.parentNode.removeChild @firstChild markup = "<svg id='wrapper' xmlns='http://www.w3.org/2000/svg'>#{markup}</svg>" $div = document.createElement 'div' $div.innerHTML = markup $svg = $div.querySelector 'svg#wrapper' for $element in $svg.children @appendChild $element enumerable : false configurable : true
我在这里写一个肮脏的方式…
用于SVG的innerHTML解决方法
http://jsfiddle.net/microbians/8ztNU/
<html> <body> <svg id="svgcanvas"> </svg> <script> var twocircles='<circle cx="253" cy="562" r="10" stroke="black" stroke-width="2" fill="red"></circle> \ <circle cx="353" cy="562" r="10" stroke="black" stroke-width="2" fill="red"></circle>' var receptacle = document.createElement('div'); var svgfragment='<svg>'+twocircles+'</svg>'; receptacle.innerHTML=''+svgfragment; var Nodes=Array.prototype.slice.call(receptacle.childNodes[0].childNodes); Nodes.forEach(function(el){document.getElementById('svgcanvas').appendChild(el)}) </script> </body> </html>
请享用!
看看innerSVG javascript shim,它提供了你想要的function。
2014更新: DOMparsing规范在Element
上定义了innerHTML
和outerHTML
,这使得这些元素在svg和xml元素上可用。 这已经在Blink发布了一段时间了,支持这个的第一个版本是Chrome 32 / Opera 19,更多细节可以在这个bugreport中find。
简短的回答是:“不,在XML世界中没有任何东西可以让你给它添加一些标记,让它自动地在插入它的位置的适当命名空间中创build所有的元素和属性。
最接近的直接答案是罗伯特所拥有的。 正如在我的评论中指出的那样,即使这样,您仍然需要在SVG文档中创build与您要插入片段的文档具有相同名称空间和前缀的片段。
相反,您可能会发现在标准的DOM方法上使用方便的方法很简单(或更容易):
// Create a named SVG element on a node, with attributes and optional text function appendTo(node,name,attrs,text){ var p,ns=appendTo.ns,svg=node,doc=node.ownerDocument; if (!ns){ // cache namespaces by prefix once while (svg&&svg.tagName!='svg') svg=svg.parentNode; ns=appendTo.ns={svg:svg.namespaceURI}; for (var a=svg.attributes,i=a.length;i--;){ if (a[i].namespaceURI) ns[a[i].localName]=a[i].nodeValue; } } var el = doc.createElementNS(ns.svg,name); for (var attr in attrs){ if (!attrs.hasOwnProperty(attr)) continue; if (!(p=attr.split(':'))[1]) el.setAttribute(attr,attrs[attr]); else el.setAttributeNS(ns[p[0]]||null,p[1],attrs[attr]); } if (text) el.appendChild(doc.createTextNode(text)); return node.appendChild(el); } function clear(node){ while (node.lastChild) node.removeChild(node.lastChild); }
有了这个,你可以做这样的事情:
var icons={ Apps : "http://img.dovov.comapps.png", Games : "http://img.dovov.comgames.png" } var wrap = document.querySelector('#container'); clear(wrap); for (var label in icons){ if (!icons.hasOwnProperty(label)) continue; var icon = appendTo(wrap,'g',{'class':'icon'}); appendTo(icon,'image',{'xlink:href':icons[label]}); appendTo(icon,'text',{x:10,y:20},label); }
这是恕我直言,比尝试使用string连接构build原始SVG标记清洁:
var svg = []; for (var label in icons){ if (!icons.hasOwnProperty(label)) continue; svg.push('<g class="icon">'); svg.push('<image xlink:href="'+icons[label]+'" />'); svg.push('<text x="10" y="20">'+label+'</text>'); svg.push('</g>'); } wrap.innerSVG = svg.join(''); // doesn't work, of course
用jQuery,你可以这样做:
假设您的svgString
在replace操作之后包含您的svg图像。
$(svgString)[0]
创build一个对应于你的string的svg标签。 然后你可以把这个元素追加到你想要的dom中来绘制图像。
我希望这有帮助
至less在Chrome和Safari上看起来,您可以将SVG元素包装在HTML元素中,并请求innerHTML
。 即使SVG源指定为绿色,以下HTML文件也会呈现红色矩形。
<body> <div id="wrapper"> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="120" height="120" viewBox="0 0 236 120"> <rect x="14" y="23" width="250" height="50" fill="green" stroke="black" stroke-width="1" /> </svg> </div> <script> var el = document.getElementById('wrapper'); var t = el.innerHTML; t = t.replace(/green/g, "red"); el.innerHTML = t; </script> </body>
更简单地说, document.querySelector('#myContainer').textContent = newContent;
有很好的支持,def。 到IE9 +,Safari,FF,Chrome。
迈克·博斯托克(Mike Bostock)是我的英雄: D3.js源代码是我对于SVG问题的一个转折点 。