简体   繁体   English

将 `tick()` 从 d3 v3 转换为 v5

[英]Converting `tick()` from d3 v3 to v5

I have a force function that works in d3 V3 and I'd like to convert it to V5.我有一个适用于 d3 V3 的force函数,我想将其转换为 V5。 I'll show the solution that works right now and then go into what's broken.我将展示现在有效的解决方案,然后再讨论问题所在。

This works in v3这适用于 v3

var force = d3.layout.force()
    .nodes(nodes)
    .size([width, height])
    .gravity(0)
    .charge(0)
    .friction(.9)
    .on("tick", tick)
    .start();

function tick(e) {

  var k = 0.03 * e.alpha;

  // Push nodes toward their designated focus.
  nodes.forEach(function(o, i) {
    var curr_act = o.act;

    var damper = .85;

    o.x += (x(+o.decade) - o.x) * k * damper;
    o.y += (y('met') - o.y) * k * damper;
    o.color = color('met');

 });

  circle
      .each(collide(.5))
      .style("fill", function(d) { return d.color; })
      .attr("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; });
}

// Resolve collisions between nodes.
function collide(alpha) {

  var quadtree = d3.geom.quadtree(nodes);

  return function(d) {
    var r = d.radius + maxRadius + padding,
        nx1 = d.x - r,
        nx2 = d.x + r,
        ny1 = d.y - r,
        ny2 = d.y + r;
    quadtree.visit(function(quad, x1, y1, x2, y2) {

      if (quad.point && (quad.point !== d)) {
        var x = d.x - quad.point.x,
            y = d.y - quad.point.y,
            l = Math.sqrt(x * x + y * y),
            r = d.radius + quad.point.radius + (d.act !== quad.point.act) * padding;
        if (l < r) {
          l = (l - r) / l * alpha;
          d.x -= x *= l;
          d.y -= y *= l;
          quad.point.x += x;
          quad.point.y += y;
        }
      }
      return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
    });
  };
}

where the object circles is defined as.其中对象circles被定义为。

var circle = svg.selectAll("circle")
    .data(nodes)
    .enter().append("circle")

And this is an example of a node.是一个节点的例子。

This is my attempt to convert it to v5这是我尝试将其转换为 v5

var force = d3.forceSimulation(nodes)
.velocityDecay(.9)
.force("center", d3.forceCenter(width / 2,height / 2))
.force("charge", d3.forceManyBody().strength())
.on("tick", tick)

I kept everything else the same except that I replaced d3.geom.quadtree(nodes) with d3.quadtree(nodes) .我不停的一切,除了我取代了相同的d3.geom.quadtree(nodes)d3.quadtree(nodes)

I am having trouble with the tick function.我在使用tick功能时遇到问题。 In the old version, the e argument prints something like this.在旧版本中, e参数打印出类似这样的内容。

在此处输入图片说明

In the new version, it prints undefined and the function breaks with Uncaught TypeError: Cannot read property 'alpha' of undefined .在新版本中,它打印 undefined 并且函数因Uncaught TypeError: Cannot read property 'alpha' of undefined中断。

Does tick() have a new format or a new way of passing arguments in v5?在 v5 中, tick()是否有新的格式或传递参数的新方式?

If you are trying to access simulation properties during the simulation's ticks, you no longer use an event passed as a parameter to the tick function.如果您尝试在模拟的滴答期间访问模拟属性,则不再使用作为参数传递给滴答函数的事件。 Instead you can access the simulation directly with this .相反,您可以使用this直接访问模拟。

From the docs:从文档:

When a specified event is dispatched, each listener will be invoked with the this context as the simulation.当指定的事件被调度时,每个监听器都会以 this 上下文作为模拟被调用。 ( docs ). 文档)。

Which means that you can access alpha, for example, with this.alpha() (or simulation.alpha() ), within the tick function in v4/v5:这意味着您可以在 v4/v5 的刻度函数中访问 alpha,例如,使用this.alpha() (或simulation.alpha() ):

 d3.forceSimulation() .velocityDecay(.9) .force("charge", d3.forceManyBody().strength()) .on("tick", tick) .nodes([{},{}]); function tick() { console.log(this.alpha()); }
 .as-console-wrapper { min-height: 100%; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM