为什么我们需要 force.on('tick'.. 在 d3
Why do we need force.on('tick'.. in d3
我正在通过从基础编写力导向图来学习 d3。我的代码是below.What我不明白force.on('tick'...
的目的
当然,如果我们使用内置的 class 作为布局,我会认为给 d3.layout.force() 节点和链接就足够了,它应该能够绘制平衡布局中的图形。
如果我注释掉 force.on('tick'... 部分,那么我所有的圆圈和线条都会出现在左上角。内部发生的事情与 svg 容器中发生的事情之间是否存在差异,因此我们需要 force.on('tick' 重绘布局以匹配当前每次都有一组内部值?
var nodes = [
{},
{},
{}
];
var links = [
{'source': 0, 'target': 1}
];
// append svg element to container
var mychart = d3.select('#chart')
.append('svg')
.attr('width', w)
.attr('height', h);
// create force layout in memory
var force = d3.layout.force()
.nodes(nodes)
.links(links)
.size([w, h]);
// append a group for each data element
var node = mychart.selectAll('circle')
.data(nodes).enter()
.append('g')
.call(force.drag);
// append circle onto each 'g' node
node.append('circle')
.attr('fill', palette.green)
.attr('r', circleWidth);
/*force.on('tick', function(e) {
node.attr('transform', function(d, i) {
return 'translate('+ d.x +', '+ d.y +')';
})
link
.attr('x1', function(d) { return d.source.x })
.attr('y1', function(d) { return d.source.y })
.attr('x2', function(d) { return d.target.x })
.attr('y2', function(d) { return d.target.y })
});*/
var link = mychart.selectAll('line')
.data(links).enter()
.append('line')
.attr('stroke', palette.gray)
force.start();
强制布局 运行 异步。也就是说,当您调用 force.start()
时,它会开始计算以确定节点在后台并行的位置。这些计算不是一步,而是长时间(几秒)的模拟 运行ning。
tick
处理函数使您能够在布局发生变化时获取布局状态(模拟已提前一个刻度)并对其进行操作——特别是重绘节点以及他们当前在模拟中的链接。
不过您不必处理 tick
事件,您可以简单地 运行 布局一定数量的步骤,然后在不处理 tick
事件的情况下绘制全部,如 this example。在 tick
处理程序函数中动态执行此操作的好处是您可以看到布局的进展情况。但是,从技术上讲,如果您只对结果感兴趣,则不需要。
我正在通过从基础编写力导向图来学习 d3。我的代码是below.What我不明白force.on('tick'...
的目的当然,如果我们使用内置的 class 作为布局,我会认为给 d3.layout.force() 节点和链接就足够了,它应该能够绘制平衡布局中的图形。
如果我注释掉 force.on('tick'... 部分,那么我所有的圆圈和线条都会出现在左上角。内部发生的事情与 svg 容器中发生的事情之间是否存在差异,因此我们需要 force.on('tick' 重绘布局以匹配当前每次都有一组内部值?
var nodes = [
{},
{},
{}
];
var links = [
{'source': 0, 'target': 1}
];
// append svg element to container
var mychart = d3.select('#chart')
.append('svg')
.attr('width', w)
.attr('height', h);
// create force layout in memory
var force = d3.layout.force()
.nodes(nodes)
.links(links)
.size([w, h]);
// append a group for each data element
var node = mychart.selectAll('circle')
.data(nodes).enter()
.append('g')
.call(force.drag);
// append circle onto each 'g' node
node.append('circle')
.attr('fill', palette.green)
.attr('r', circleWidth);
/*force.on('tick', function(e) {
node.attr('transform', function(d, i) {
return 'translate('+ d.x +', '+ d.y +')';
})
link
.attr('x1', function(d) { return d.source.x })
.attr('y1', function(d) { return d.source.y })
.attr('x2', function(d) { return d.target.x })
.attr('y2', function(d) { return d.target.y })
});*/
var link = mychart.selectAll('line')
.data(links).enter()
.append('line')
.attr('stroke', palette.gray)
force.start();
强制布局 运行 异步。也就是说,当您调用 force.start()
时,它会开始计算以确定节点在后台并行的位置。这些计算不是一步,而是长时间(几秒)的模拟 运行ning。
tick
处理函数使您能够在布局发生变化时获取布局状态(模拟已提前一个刻度)并对其进行操作——特别是重绘节点以及他们当前在模拟中的链接。
不过您不必处理 tick
事件,您可以简单地 运行 布局一定数量的步骤,然后在不处理 tick
事件的情况下绘制全部,如 this example。在 tick
处理程序函数中动态执行此操作的好处是您可以看到布局的进展情况。但是,从技术上讲,如果您只对结果感兴趣,则不需要。