假设我已经用d3.js创建了一个svg:
svg = d3.select('.svgContainer').append("svg")
.attr("width", '100%')
.attr("height", '100%')
.call(d3.zoom().on("zoom", function () {
svg.attr("transform", d3.event.transform)
}))
.append("g");
,我现在想向其添加不同的组(动态地并来自不同的文件)。例如一个:
<svg>
<g id="myGroup">
<rect width="100" height="100" fill="blue" />
</g>
</svg>
我知道,我可以像这样添加整个svg(假设文件名为test.svg):
d3.xml("test.svg").then(function(xml) {
var svgNode = xml.getElementsByTagName("svg")[0];
svg.node().appendChild(svgNode);
});
但是,这会产生以下DOM:
svg
-svg
--myGroup
但是由于我需要相对于主要svg转换组,因此我需要以下DOM结构:
svg
-myGroup
--(eventually more dynamically added groups)
我尝试了以下操作并获得了正确的DOM,但是该组未显示在我的svg中:
d3.xml("test.svg").then(function(xml) {
var svgGroup = xml.getElementById("myGroup");
svg.node().append(svgGroup);
});
编辑:我发现这应该已经可以了,问题是我的SVG内部有几个关键的<defs>
(例如,渐变)。当我仅添加组时,我丢失了它们。最后,我将<g>
包裹在<defs>
周围,现在一切正常。
答案 0 :(得分:3)
只是对accepted answer的补充:如果您想使用纯D3解决方案,则可以将selection.append
与一个函数一起使用。就您而言:
d3.xml(svgfile).then(function(xml) {
var svgNode = d3.select(xml).select("#MyGroup");
svg.append(() => svgNode.node()) ;
});
或更短:
d3.xml(svgfile).then(function(xml) {
svg.append(() => d3.select(xml).select("#MyGroup").node()) ;
});
以下是使用另一个答案中链接的Wikipedia SVG的演示:
var svgfile = "https://simple.wikipedia.org/static/images/mobile/copyright/wikipedia-wordmark-en.svg";
var svg = d3.select('body').append("svg")
.attr("width", '120')
.attr("height", '20');
d3.xml(svgfile).then(function(xml) {
var svgNode = d3.select(xml).select("#Wikipedia");
svg.append(() => svgNode.node());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
答案 1 :(得分:1)
您快到了。我已经说明了添加元素in this codepen的两种方法。第一种方法的问题在于svgNode
不是node
,而是nodeList
。您可以在循环中添加列表中的每个节点,如代码所示:
...
var toAdd = svgNode.childNodes;
for (var i = 0; i < svgNode.childElementCount; i++){
svg.node().appendChild(toAdd[i]);
}
...
关于第二种方法,我不能说有什么问题。我已经从其他svg文件导入了路径,该路径显示在下部。我更改的唯一细节是我显式设置了svg元素的大小,而不是设置为100%
。是否有可能因为它不在可见部分之外而未渲染?