d3:Multi-Foci Force关键代码组件理解
d3: Multi-Foci Force key code component understanding
多焦点力量的真正魔法在这里完成;
function tick(e) {
var k = .1 * e.alpha;
// Push nodes toward their designated focus.
nodes.forEach(function(o, i) {
o.y += (foci[o.id].y - o.y) * k;
o.x += (foci[o.id].x - o.x) * k;
});
node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
}
但我希望能对正在发生的事情进行一些澄清。
alpha,我相信,是一种力方法,它控制力停止的速率,接受范围 [0, 1] 中的值 - 较高的值导致力减慢停止速度较慢,较低的值更快。
然后我们遍历原始数组并将 x 和 y 位置(最初不存在,因此在这个 forEach 循环的第一次迭代中首次分配)增加 k * x 和焦点的 y 分量。
最终它们将始终朝着指定的 x 和 y 位置移动,但是我们如何保证我们根据本身基于 alpha 的 k 值将它们到达那里?节点沿 x 轴和 y 轴移动的范围是否由 .1 常数控制?设置此 higher/lower 意味着 more/less 向焦点移动?
最后为什么要变换节点呢?我会理解
node.attr("cx", function(d) { return d.x}) 和 y 相同。为什么要转型?
致谢
jfiddle - https://jsfiddle.net/hiwilson1/dL9r22ny/
更新:我怀疑我的问题的最后一部分,为什么我们要变换节点,是因为我们移动的是 g 元素而不是圆形元素,而且我们不能在 g 元素上使用 cx 和 cy。仍然不确定我们为什么要翻译它们 d.x 和 d.y,这不会将它们从任意分配的 d.x 和 d.y 值中移动到有效地加倍这些位置吗? (如果我们从 [10, 10] 开始并翻译另一个 [10, 10],我们会在 [20, 20] 结束吗?)
动画由alpha
驱动。这是一个永远相同的几何级数:在.start()
中设置为0.1,每次tick乘以0.99,当小于0.005
时动画停止
alpha: 0.0990
alpha: 0.0980
alpha: 0.0970
alpha: 0.0961
alpha: 0.0951
alpha: 0.0941
...等等
force.tick = function() {
if ((alpha *= .99) < .005) {
event.end({
type: "end",
alpha: alpha = 0
});
return true;
}
//other code...
};
表示布局中的"heat",因为它是用来决定节点的速度的。这类似于气体中的温度,它与其分子的平均动能成正比。 "cooling" 被预编程为始终是当前 "temperature".
的 -1%
元素的初始位置也在 .start()
函数中设置为 Math.random() * size
x 和 y,其中大小分别为宽度和高度。这是在 tick
函数中的第一个 forEach
之前完成的。
function tick(e) {
//var k = .1 * e.alpha;
var k = .1 * e.alpha;
log.text('alpha: ' + d3.format(".4f")(e.alpha * 1000))
// Push nodes toward their designated focus.
nodes.forEach(function (o, i) {
o.y += (foci[o.id].y - o.y) * k;
o.x += (foci[o.id].x - o.x) * k;
});
在上面的forEach
语句中,如果元素y位置大于焦点y位置,那么它会被赋予较小的y,x位置类似。这意味着他们将以与其距离成正比的速度移向焦点。比例常数 k
是 0.1*alpha
,随着动画的进行,它从 k = 0.1*0.1
呈几何递减到 k = 0.1*0.005
。最终位置是其初始位置和 k
以及其他重力、电荷和摩擦力的函数。
节点是 g
个元素,除了其子元素的引用(定位上下文)外,没有定位。这是包含 svg
元素的原点(左上角),它的位置是页面流和 CSS 定位的结果。 g
元素的定位上下文可以通过它们的变换 属性 来改变,这被它们的所有子元素继承。如果没有 g 元素,圆圈和文本元素都必须单独定位,这样工作就减半了。如果没有转换,所有圆圈和文本都将定位在 svg
元素左上角的中心。
每个订单号计算的新头寸是绝对值,而不是值的变化。
节点位置的变化是(foci[o.id].y - o.y) * k
,这会将它们移向它们的焦点。这是 "added" 到现有值(尽管它可能是负数)并存储在节点数据上(o.x
和 o.y
),此语句
node.attr("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; });
使用新数据 (d
) 更新翻译,它仍然相对于 svg
原点。它是 transform,而不是 move,因此它不会相对于当前位置平移,它会改变相对于 svg
元素原点(这是 g
的定位上下文)。所以如果我们从 [10,10] 开始并且新的计算是 [10,10] 那么位置将保持在 [10,10] 相对于 svg
定位上下文。
多焦点力量的真正魔法在这里完成;
function tick(e) {
var k = .1 * e.alpha;
// Push nodes toward their designated focus.
nodes.forEach(function(o, i) {
o.y += (foci[o.id].y - o.y) * k;
o.x += (foci[o.id].x - o.x) * k;
});
node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
}
但我希望能对正在发生的事情进行一些澄清。
alpha,我相信,是一种力方法,它控制力停止的速率,接受范围 [0, 1] 中的值 - 较高的值导致力减慢停止速度较慢,较低的值更快。
然后我们遍历原始数组并将 x 和 y 位置(最初不存在,因此在这个 forEach 循环的第一次迭代中首次分配)增加 k * x 和焦点的 y 分量。
最终它们将始终朝着指定的 x 和 y 位置移动,但是我们如何保证我们根据本身基于 alpha 的 k 值将它们到达那里?节点沿 x 轴和 y 轴移动的范围是否由 .1 常数控制?设置此 higher/lower 意味着 more/less 向焦点移动?
最后为什么要变换节点呢?我会理解
node.attr("cx", function(d) { return d.x}) 和 y 相同。为什么要转型?
致谢
jfiddle - https://jsfiddle.net/hiwilson1/dL9r22ny/
更新:我怀疑我的问题的最后一部分,为什么我们要变换节点,是因为我们移动的是 g 元素而不是圆形元素,而且我们不能在 g 元素上使用 cx 和 cy。仍然不确定我们为什么要翻译它们 d.x 和 d.y,这不会将它们从任意分配的 d.x 和 d.y 值中移动到有效地加倍这些位置吗? (如果我们从 [10, 10] 开始并翻译另一个 [10, 10],我们会在 [20, 20] 结束吗?)
动画由alpha
驱动。这是一个永远相同的几何级数:在.start()
中设置为0.1,每次tick乘以0.99,当小于0.005
alpha: 0.0990
alpha: 0.0980
alpha: 0.0970
alpha: 0.0961
alpha: 0.0951
alpha: 0.0941
...等等
force.tick = function() {
if ((alpha *= .99) < .005) {
event.end({
type: "end",
alpha: alpha = 0
});
return true;
}
//other code...
};
表示布局中的"heat",因为它是用来决定节点的速度的。这类似于气体中的温度,它与其分子的平均动能成正比。 "cooling" 被预编程为始终是当前 "temperature".
的 -1%元素的初始位置也在 .start()
函数中设置为 Math.random() * size
x 和 y,其中大小分别为宽度和高度。这是在 tick
函数中的第一个 forEach
之前完成的。
function tick(e) {
//var k = .1 * e.alpha;
var k = .1 * e.alpha;
log.text('alpha: ' + d3.format(".4f")(e.alpha * 1000))
// Push nodes toward their designated focus.
nodes.forEach(function (o, i) {
o.y += (foci[o.id].y - o.y) * k;
o.x += (foci[o.id].x - o.x) * k;
});
在上面的forEach
语句中,如果元素y位置大于焦点y位置,那么它会被赋予较小的y,x位置类似。这意味着他们将以与其距离成正比的速度移向焦点。比例常数 k
是 0.1*alpha
,随着动画的进行,它从 k = 0.1*0.1
呈几何递减到 k = 0.1*0.005
。最终位置是其初始位置和 k
以及其他重力、电荷和摩擦力的函数。
节点是 g
个元素,除了其子元素的引用(定位上下文)外,没有定位。这是包含 svg
元素的原点(左上角),它的位置是页面流和 CSS 定位的结果。 g
元素的定位上下文可以通过它们的变换 属性 来改变,这被它们的所有子元素继承。如果没有 g 元素,圆圈和文本元素都必须单独定位,这样工作就减半了。如果没有转换,所有圆圈和文本都将定位在 svg
元素左上角的中心。
每个订单号计算的新头寸是绝对值,而不是值的变化。
节点位置的变化是(foci[o.id].y - o.y) * k
,这会将它们移向它们的焦点。这是 "added" 到现有值(尽管它可能是负数)并存储在节点数据上(o.x
和 o.y
),此语句
node.attr("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; });
使用新数据 (d
) 更新翻译,它仍然相对于 svg
原点。它是 transform,而不是 move,因此它不会相对于当前位置平移,它会改变相对于 svg
元素原点(这是 g
的定位上下文)。所以如果我们从 [10,10] 开始并且新的计算是 [10,10] 那么位置将保持在 [10,10] 相对于 svg
定位上下文。