Svg D3:追加选择的重复项
我想创建一个javascript函数,它可以接受一般的D3选择,并将其副本附加到SVG对象 下面是一个最低限度的工作示例:Svg D3:追加选择的重复项,svg,d3.js,Svg,D3.js,我想创建一个javascript函数,它可以接受一般的D3选择,并将其副本附加到SVG对象 下面是一个最低限度的工作示例: <!DOCTYPE html> <meta charset="utf-8"> <body> <script src="http://d3js.org/d3.v3.min.js"></script> <script> svg = d3.select("body").append("svg")
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
svg = d3.select("body").append("svg")
.attr("width", 300)
.attr("height", 300);
circle = svg.append("circle")
.attr("cx", 100)
.attr("cy", 100)
.attr("r", 20)
function clone_selection(x, i) {
for (j = 0; j < i; j++) {
// Pseudo code:
// svg.append(an exact copy of x, with all the attributes)
}
}
clone_selection(circle, 5);
</script>
svg=d3。选择(“正文”)。追加(“svg”)
.attr(“宽度”,300)
.attr(“高度”,300);
circle=svg.append(“circle”)
.attr(“cx”,100)
.attr(“cy”,100)
.attr(“r”,20)
功能克隆_选择(x,i){
对于(j=0;j
迈克·博斯托克说这是不可能的,但那是很久以前的事了
有人对如何实现这一目标有什么新想法吗?请记住,在函数
clone\u selection
中,我们不知道x中的svg元素是什么。感谢@nrabinowitz为我指出
元素
以下是带有工作解决方案的MWE:
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
svg = d3.select("body").append("svg")
.attr("width", 300)
.attr("height", 300);
circle = svg.append("circle")
.attr("id", "circleToClone")
.attr("cx", 100)
.attr("cy", 100)
.attr("r", 20)
function clone_selection(object, i) {
for (j = 0; j < i; j++) {
// Here's the solution:
cloned_obj = svg.append("use")
.attr("xlink:href","#" + object.attr("id"));
}
}
clone_selection(circle, 5);
</script>
svg=d3。选择(“正文”)。追加(“svg”)
.attr(“宽度”,300)
.attr(“高度”,300);
circle=svg.append(“circle”)
.attr(“id”,“circleToClone”)
.attr(“cx”,100)
.attr(“cy”,100)
.attr(“r”,20)
功能克隆_选择(对象,i){
对于(j=0;j
还有一种可能性:做事要长远。这解决了使用
元素时无法单独设置样式
或变换
属性的问题
我很惊讶神奇的d3js
库在本机上没有这样的功能,但下面是我的技巧:
function clone_d3_selection(selection, i) {
// Assume the selection contains only one object, or just work
// on the first object. 'i' is an index to add to the id of the
// newly cloned DOM element.
var attr = selection.node().attributes;
var length = attr.length;
var node_name = selection.property("nodeName");
var parent = d3.select(selection.node().parentNode);
var cloned = parent.append(node_name)
.attr("id", selection.attr("id") + i);
for (var j = 0; j < length; j++) { // Iterate on attributes and skip on "id"
if (attr[j].nodeName == "id") continue;
cloned.attr(attr[j].name,attr[j].value);
}
return cloned;
}
功能克隆\u d3\u选择(选择,i){
//假设选择仅包含一个对象,或仅包含一个工作对象
//在第一个对象上,“i”是要添加到
//新克隆的DOM元素。
var attr=selection.node().attributes;
变量长度=属性长度;
var node_name=selection.property(“nodeName”);
var parent=d3.select(selection.node().parentNode);
var cloned=parent.append(节点名称)
.attr(“id”,selection.attr(“id”)+i);
对于(var j=0;j
此函数对d3的选择进行深度复制,并返回复制元素的选择:
function cloneSelection(appendTo, toCopy, times) {
toCopy.each(function() {
for (var i = 0; i < times; i++) {
var clone = svg.node().appendChild(this.cloneNode(true));
d3.select(clone).attr("class", "clone");
}
});
return appendTo.selectAll('.clone');
}
函数克隆选择(附录、复制、时间){
toCopy.each(函数(){
对于(变量i=0;i<次;i++){
var clone=svg.node().appendChild(this.cloneNode(true));
d3.选择(克隆).attr(“类”、“克隆”);
}
});
返回appendTo.selectAll('.clone');
}
见演示
如果选择的toCopy包含多个元素,此函数也可以使用
但是请注意,它会复制所有内容,以及所有内部元素的类、ID和其他属性,如果您在其他地方直接引用内部元素,这可能会破坏您的代码。因此,请注意您的选择。有一个父母,这使克隆人与原始人区别开来,并在选择链中提到它将使你安全
一个合理的做法(如果你真的非常需要id的话)是只在你正在复制的内容的外部元素上设置id,你可以通过修改函数来轻松地更改它:
d3.select(clone).attr(“class”,“clone”).attr(“id”,“clone-”+i)
回答这个问题可能有点晚,但当我开发出自己的解决方案时,我发现了这个问题。这就是我创建副本的方式
d3.select("#some_id")
.append("div")
.attr("class","some_other_id")
.each(function(d) {
for (var i = 1; i < number_duplicate; i++) {
d3.select("#some_other_id")
.append("button")
.attr("type","button")
.attr("class","btn-btn")
.attr("id","id_here")
.append("div")
.attr("class","label")
.text("text_here")
}
});
d3.选择(“某个id”)
.附加(“div”)
.attr(“类”、“某些其他id”)
.每个功能(d){
对于(变量i=1;i
我在其上创建一个div do.each(),并在each函数中放入一个for循环。
这个数字会告诉我复制品的数量
变化是可能的,可能一秒钟就行了,等等。可能是穷人的版本——我不是职业选手。我想听听你的反馈。四年零四个月后。。。我制作了这个D3插件。
您正在寻找类似的产品吗?您需要一个真正的克隆,还是元素可以工作?谢谢您的评论。不过,这两种方法都不适用于一般的D3选择。关于这一点还有更多的讨论,但我想Mike Bostock提到的selection.clone()方法还没有实现。@nrabinowitz我实际上想要一个对象的浅拷贝,而不是克隆。这使元素更合适,对吗?我大概可以做
svg.selectAll(“use”).data(someData.enter().append().attr(“xlink:href”,“myID”)
Hmm。。我刚刚对此进行了测试,结果表明此方法并不理想,因为您无法将样式
或转换
属性应用于
对象。这意味着您必须使用初始对象的真实副本。回到绘图板…嗯-我很确定您可以覆盖use
元素上的属性,如fill
、cx
、cy
,等等。我很惊讶你不能使用transform
,但是你总是可以用g
包装元素,并应用转换和样式。这应该是更好的答案:)非常感谢。就我所知,这也是更好的答案@LondonRob,由于无法覆盖fill、cx、cy等,我发现如果原始svg有以下任何一种