D3.js attr()元';除非通过匿名函数返回属性,否则不能更改属性
所有圆都将具有相同的y对齐,而预期的行为是将每个圆绘制在另一个圆的下方。奇怪的是,如果我通过一个匿名函数返回D3.js attr()元';除非通过匿名函数返回属性,否则不能更改属性,d3.js,D3.js,所有圆都将具有相同的y对齐,而预期的行为是将每个圆绘制在另一个圆的下方。奇怪的是,如果我通过一个匿名函数返回someScaleObject(++k),这就达到了预期的效果。为什么?作者还在匿名函数的范围内声明了一个d变量,尽管它没有任何用处。有人能解释为什么吗 var k = -1; someCircle.attr("cy", someScaleObject(++k)); 完整的代码可以在下面找到,并从D3中为不耐烦的人绘制 和html文件 // keys.js funct
someScaleObject(++k)
,这就达到了预期的效果。为什么?作者还在匿名函数的范围内声明了一个d
变量,尽管它没有任何用处。有人能解释为什么吗
var k = -1;
someCircle.attr("cy", someScaleObject(++k));
完整的代码可以在下面找到,并从D3中为不耐烦的人绘制
和html文件
// keys.js
function makeKeys() {
var ds1 = [["Mary", 1], ["Jane", 4], ["Anne", 2]];
var ds2 = [["Anne", 5], ["Jane", 3]];
var scX = d3.scaleLinear().domain([0, 6]).range([50, 300]),
scY = d3.scaleLinear().domain([0, 3]).range([50, 150]);
var j = -1, k = -1;
var svg = d3.select("#keys");
svg.selectAll("text")
.data(ds1).enter().append("text")
.attr("x", 20).attr("y", function (d) {
return scY(++j);
}).text(function (d) {
return d[0];
});
svg.selectAll("circle").data(ds1).enter().append("circle")
.attr("r", 5).attr("fill", "red")
.attr("cx", function (d) {
return scX(d[1]);
})
.attr("cy", function (d) {
return scY(++k); // this is what concerns me
});
svg.on("click", function () {
var cs = svg.selectAll("circle").data(ds2, function (d) {
return d[0];
});
cs.transition().duration(1000).attr("cx", function (d) {
return scX(d[1]);
})
cs.exit().attr("fill", "blue");
})
}
如下所示:
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="d3.js"></script>
<script src="keys.js"></script>
</head>
<body onload="makeKeys()">
<svg id="keys" width="300" height="150"></svg>
</body>
</html>
您没有将函数传递给
selection.attr()
,而是执行someScaleObject(++k)
并传递其返回值。如果将函数以外的内容传递给第二个参数selection.attr()
,则对所有元素使用相同的值-这就是为什么圆的位置都相同的原因
您可以传递函数而不执行它:
someCircle.attr("cy", someScaleObject(++k));
但是,如果要将某个整数传递给此函数,D3会将三个变量传递给传递给selection.attr()
——数据、当前索引和选择中的DOM节点组。这些都是按这个顺序通过的。在您的例子中,您希望向函数传递一些其他变量,因此此方法不起作用
您可以构建一些ScaleObject来跟踪或访问函数中的k
本身,这样就不需要将其作为参数传递。或者,我们可以将函数嵌套在匿名函数中:
someCircle.attr("cy", someScaleObject);
这允许我们将数据、索引和节点组以外的参数传递给要执行的函数。通过这种方式,selection.attr()
被传递一个函数,当对选择中的每个元素执行时,执行someScaleObject
所需的次数
然而
虽然上述内容在D3方面很有用,但在您的特定情况下,将k
传递给缩放对象的必要性尚不清楚,因为k
表示每个元素的索引。因此,不是:
someCircle.attr("cy", function() { return someScaleObject(++k) });
我们可以简单地使用:
var k = -1;
selection.attr("cy", function() { return scY(++k); })
因为传递给
.attr()
的函数的第二个参数是所选元素的索引。D3已经追踪到了。实际上,我没有意识到索引是需要外部跟踪的东西的用例。您不是通过.attr(“cx”,functionName(param))
传递函数,而是传递函数的返回值。这意味着该函数只执行一次。如果要传递函数,可以使用.attr(“cx”,functionName)
。包装函数允许您在不立即执行的情况下传递参数,允许为选择中的每个元素执行该参数(如果.attr()的第二个参数是函数,则为每个元素执行),这种定位方法似乎不是惯用的-j
等于元素的索引,这是提供给.attr:function(d,i){…}
的函数中的第二个参数-因此不清楚为什么声明一个新变量来跟踪索引更可取。至于在函数声明中包含d
,但不使用它——这可能是在审查中遗漏的习惯,如果不使用它,您可以删除它(前提是不要使用d3传递给函数的其他参数:索引和节点)。使用索引来定位元素,而不是j
和k
。非常好的答案。如何将问题标记为已回答?我可以在一小段时间内发布正确的答案,因为只有答案可以标记为已回答问题,而评论不能。
var k = -1;
selection.attr("cy", function() { return scY(++k); })
selection.attr("cy", function(d,i) { return scY(i); })