🏠 back to Observable

Nodes appearing from corner, not center of map, when using d3.force

Hi, I have a map of locations positioned using d3.force, that updates using a data scrubber. The initial and all new nodes transition from the upper corner [0,0] as they are projected to their correct locations. I’d like them to appear from the center instead, as they do here.

Note, nodes also move from one cluster to another, which seems to be working.

Any idea how to do this?

My notebook Updating positions , using d3-force / Mathew Brown / Observable

Thanks

You need to initialize your node positions to the map center, e.g. (note the added object at the end):

      nodes = nodes.map(d => Object.assign(old.get(d.IMO_number) || {}, d, {x: width/2, y: height/2}));

Hmm, that makes sense but with my implementation, all the nodes then start from the center with every update, but I just want the new nodes to start from there, while the rest should remain where they are.

… which is odd, because from your implemetation it looks like only new nodes get assigned an initial x,y of width/2,hight/2. So I’m not sure why they existing nodes are also starting from there…

I also note that this implementation does specify an initial position. Indeed, this is what I’d like to replicate, new nodes ‘appear’ close to where they will end up.

Object.assign applies properties from right to left. In order to retain previously set x/y properties, they need to be listed before d.

And instead of half width/height, you initialize with the centroid:

      const center = d => {
        const [x, y] = projection(d.feature.centroid);
        return {x, y};
      };
      nodes = nodes.map(d => Object.assign(old.get(d.IMO_number) || center(d), d));

I would also suggest that you calculate/project the centers only once and then cache them.

1 Like

Thank you so much! I had output the results of nodes after Object.assign and it seemed like they were preserving their original values… but I guess not.

I’ve not used Object.assign much, but now that I see how handy it is, will definitely make use of it more. Thanks again.