在HTML中,我可以通过提供字符串形式的模板来构建一个简单的模板系统,替换它的某些部分,然后使用innerHTML
将其分配给某个容器。
var templ = '<span>{myText}</span>'
var newContent = templ.replace( '{myText}', someVariable );
document.querySelector( '#myContainer' ).innerHTML = newContent;
这样我就可以利用浏览器的HTML解析器,而不必重复使用document.createElement()
。如果模板超出一些元素,那么后者可能会非常麻烦。
但是,在SVG中,元素没有innerHTML
甚至innerSVG
的属性。
所以我的问题是:我可以在SVG ro中使用什么类似于上面示例中的方法,还是我坚持使用document.createElement()
(或者某些使用它的lib)?
与我的问题一样:Vanilla JavaScript解决方案是首选,但任何提供解决方案的lib的指针都会受到赞赏。
答案 0 :(得分:11)
您可以使用DOMParser来解析XML: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));
答案 1 :(得分:6)
查看innerSVG javascript shim,它提供了您想要的功能。
2014年更新 DOM parsing spec在innerHTML
上定义outerHTML
和Element
,这使得这些在svg和xml元素上可用。这已经在Blink发布了一段时间了,支持这个的第一个版本是Chrome 32 / Opera 19,更多细节可以在this bugreport中找到。
答案 2 :(得分:4)
我的内部SVG垫片怎么样? 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
答案 3 :(得分:4)
在这里,我写了一个肮脏的方式...
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>
享受!
答案 4 :(得分:3)
简短的回答是“不,在XML世界中没有任何东西可以让你提供一些标记,并让它自动在插入它的位置的适当命名空间中创建所有元素和属性。 “
最接近的直接答案是@Robert所拥有的。正如我的评论中所指出的那样,即使这样,您也需要在SVG文档中创建任何片段,这些片段与您要插入片段的文档具有相同的名称空间和前缀。
相反,您可能会发现在标准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 : "/images/apps.png",
Games : "/images/games.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);
}
这是恕我直言,而不是尝试使用字符串连接构建原始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
答案 5 :(得分:1)
使用jQuery,你可以这样做:
我们假设您的svgString
包含替换操作后的svg图像。
$(svgString)[0]
创建与您的字符串对应的svg标记。然后,您可以将此元素附加到dom中所需的位置以绘制图像。
我希望这会有所帮助
答案 6 :(得分:1)
至少在Chrome和Safari上,您可以将SVG元素包装在HTML元素中并请求innerHTML
。以下HTML文件呈现红色矩形,即使SVG源指定绿色。
<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>
答案 7 :(得分:1)
更简单的说,document.querySelector('#myContainer').textContent = newContent;
有很好的支持,def。到IE9 +,Safari,FF,Chrome。
迈克博斯托克是我的英雄,这些东西:D3.js source code是我对SVG问题的首选。