每个函数和 this 关键字如何在 d3 中协同工作?[链接转换]
How does each function and this keyword work together in d3?[chaining transitions]
我正在使用 d3 库并且很难理解一些结构,希望有经验的人给我一些指导!
<!DOCTYPE html>
<html lang="en">
<head>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>
<body>
<script>
var svg=d3.select("body").append("svg").attr("width",800).attr("height",1000);
svg.selectAll("circle")
.data(d3.range(10)).enter().append("circle")
.attr("cx",function(d){return d;})
.attr("cy",function(d){return d*50;})
.attr("r",function(d){return d;})
.transition().duration(4000).style("fill","red")
.each("end",svg.selectAll(this).transition().duration(4000)
.attr("cx",function(d){return d*10;}));
</script>
</body>
</html>
据我所知,这应该创建圆圈,然后过渡颜色以用红色填充它们,然后更改每个圆圈的 "cx" 属性。至少,这就是我想做的。有人可以解释一下方法链接的确切工作原理以及如何使用 each() 函数和 this 关键字吗?
在这种情况下,您的 'this' 将不会引用任何 d3 对象,因为 this 是在与您的 <script>
标记相同的范围内计算的,后者在非严格模式下引用到 window
对象。
我建议您尝试从不过渡开始,然后在基础工作正常后逐渐添加。
你的代码的基本轮廓是这样的:
- 根据范围1-10生成数据集
- 如果这些数据对象分别创建一个圆圈
- 所有的对象都引用了它们各自的值,所以它们实际上是数字,你用它来计算它们的位置(x,y)和大小(r)
- 然后你转换他们的背景
- 然后你告诉它监听一个"end"事件并执行一段代码。
第 5 步失败了。我认为这基本上就是您想要的:
var svg=d3.select("body").append("svg").attr("width",800).attr("height",1000);
svg.selectAll("circle")
.data(d3.range(10))
.enter()
.append("circle")
.attr("cx",function(d){return d;})
.attr("cy",function(d){return d*50;})
.attr("r",function(d){return d;})
.transition()
.duration(4000)
.style("fill","red")
// attach a handler to all affected objects and listen
// to the "end" event:
.each("end", function() { console.log(this, arguments); })
.transition()
.duration(4000)
.attr("cx",function(d){return d*10;})
// do it again
.each("end", function() { console.log(this, arguments); })
;
默认情况下 transition
效果是链接的(参见 https://github.com/mbostock/d3/wiki/Transitions#transition)
根据我的经验,很多 为 d3 考虑一个合理的缩进会有所帮助,因为它可以帮助您了解 'scope' 目前正在做什么。
顺便说一句,您的代码中还没有随机组件,所以不要指望它会做任何您不告诉它做的事情;)
您在调试器中回答此类问题的方式。为了完全确定答案,我提取了可以设置断点的内联函数:
function resize() {
svg.selectAll(this).transition().duration(4000) //set breakpoint here
.attr("cx",function(d){return d*10;})
}
var svg=d3.select("body").append("svg")
.attr("width",800)
.attr("height",1000);
svg.selectAll("circle")
.data(d3.range(10)).enter().append("circle")
.attr("cx",function(d){return d;})
.attr("cy",function(d){return d*50;})
.attr("r",function(d){return d;})
.transition().duration(4000).style("fill","red")
.each("end",resize);
当您设置断点时,您会看到 this
的值可能是您期望的值:当前 DOM 元素,一个 '[object SVGCircleElement]'
。您可能还会检查 arguments
并发现传递给 resize
的参数是 d
和 i
。这可能不是一个令人满意的答案,因为您的代码不起作用。
您的下一个问题可能是如何调整大小才能正常工作。我不知道为什么 svg.selectAll(this)
不起作用,但如果我们调用 d3.select(this)
,该方法确实可以正常工作。
function resize(d,i) {
d3.select(this).transition().duration(4000)
.attr("cx",function(d){return d*10;})
}
如果您想内联调整大小,请不要忘记将您的参数设置为回调,而不是声明:
.each("end",function (d) { d3.select(this).transition().duration(4000).attr("cx",d*10) });
另外,您可以看到 transition.each([type],listener) 的文档说应该首选链式转换 (transition.transition
)。实现所需功能的标准方法只是链接转换:
.transition()
.duration(4000)
.style("fill","red")
.transition()
.duration(4000)
.attr("cx", function (d) { return d*10});
我正在使用 d3 库并且很难理解一些结构,希望有经验的人给我一些指导!
<!DOCTYPE html>
<html lang="en">
<head>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>
<body>
<script>
var svg=d3.select("body").append("svg").attr("width",800).attr("height",1000);
svg.selectAll("circle")
.data(d3.range(10)).enter().append("circle")
.attr("cx",function(d){return d;})
.attr("cy",function(d){return d*50;})
.attr("r",function(d){return d;})
.transition().duration(4000).style("fill","red")
.each("end",svg.selectAll(this).transition().duration(4000)
.attr("cx",function(d){return d*10;}));
</script>
</body>
</html>
据我所知,这应该创建圆圈,然后过渡颜色以用红色填充它们,然后更改每个圆圈的 "cx" 属性。至少,这就是我想做的。有人可以解释一下方法链接的确切工作原理以及如何使用 each() 函数和 this 关键字吗?
在这种情况下,您的 'this' 将不会引用任何 d3 对象,因为 this 是在与您的 <script>
标记相同的范围内计算的,后者在非严格模式下引用到 window
对象。
我建议您尝试从不过渡开始,然后在基础工作正常后逐渐添加。
你的代码的基本轮廓是这样的:
- 根据范围1-10生成数据集
- 如果这些数据对象分别创建一个圆圈
- 所有的对象都引用了它们各自的值,所以它们实际上是数字,你用它来计算它们的位置(x,y)和大小(r)
- 然后你转换他们的背景
- 然后你告诉它监听一个"end"事件并执行一段代码。
第 5 步失败了。我认为这基本上就是您想要的:
var svg=d3.select("body").append("svg").attr("width",800).attr("height",1000);
svg.selectAll("circle")
.data(d3.range(10))
.enter()
.append("circle")
.attr("cx",function(d){return d;})
.attr("cy",function(d){return d*50;})
.attr("r",function(d){return d;})
.transition()
.duration(4000)
.style("fill","red")
// attach a handler to all affected objects and listen
// to the "end" event:
.each("end", function() { console.log(this, arguments); })
.transition()
.duration(4000)
.attr("cx",function(d){return d*10;})
// do it again
.each("end", function() { console.log(this, arguments); })
;
默认情况下 transition
效果是链接的(参见 https://github.com/mbostock/d3/wiki/Transitions#transition)
根据我的经验,很多 为 d3 考虑一个合理的缩进会有所帮助,因为它可以帮助您了解 'scope' 目前正在做什么。
顺便说一句,您的代码中还没有随机组件,所以不要指望它会做任何您不告诉它做的事情;)
您在调试器中回答此类问题的方式。为了完全确定答案,我提取了可以设置断点的内联函数:
function resize() {
svg.selectAll(this).transition().duration(4000) //set breakpoint here
.attr("cx",function(d){return d*10;})
}
var svg=d3.select("body").append("svg")
.attr("width",800)
.attr("height",1000);
svg.selectAll("circle")
.data(d3.range(10)).enter().append("circle")
.attr("cx",function(d){return d;})
.attr("cy",function(d){return d*50;})
.attr("r",function(d){return d;})
.transition().duration(4000).style("fill","red")
.each("end",resize);
当您设置断点时,您会看到 this
的值可能是您期望的值:当前 DOM 元素,一个 '[object SVGCircleElement]'
。您可能还会检查 arguments
并发现传递给 resize
的参数是 d
和 i
。这可能不是一个令人满意的答案,因为您的代码不起作用。
您的下一个问题可能是如何调整大小才能正常工作。我不知道为什么 svg.selectAll(this)
不起作用,但如果我们调用 d3.select(this)
,该方法确实可以正常工作。
function resize(d,i) {
d3.select(this).transition().duration(4000)
.attr("cx",function(d){return d*10;})
}
如果您想内联调整大小,请不要忘记将您的参数设置为回调,而不是声明:
.each("end",function (d) { d3.select(this).transition().duration(4000).attr("cx",d*10) });
另外,您可以看到 transition.each([type],listener) 的文档说应该首选链式转换 (transition.transition
)。实现所需功能的标准方法只是链接转换:
.transition()
.duration(4000)
.style("fill","red")
.transition()
.duration(4000)
.attr("cx", function (d) { return d*10});