I received a question from a commentor asking how one might use the Pan and Zoom demo with a force layout. I came up with a couple of ways to do it.
Option #1
The first variation shows the quick and dirty approach which essentially bypasses the nice, reusable structures I spent time implementing in the first demo. I simply added a method named ‘addCircles()’ to the canvas which takes an array and creates a data-bound selection of circles. Then that selection is passed to the forcelayout:
See the Pen gmult by Bill White (@billdwhite) on CodePen.
Option #2
The second variation tries something a little different. The commenter wanted to take advantage of the ‘addItem()’ method in the canvas. This means that we need to modularize the circles themselves rather than work with a typical d3 selection which is referenced by the force layout. I added a forcecircle.js class which represents each circle being shown on the canvas. This lets us create each one individually and we can add them at runtime whenever we want. In the demo below you can see I start with a group of circles and the ‘add’ button can be used to append new ones at runtime:
See the Pen d3 Minimap Pan and Zoom Demo – Force Directed 1 by Bill White (@billdwhite) on CodePen.
There are lots of improvements that I think could be made here. While this setup works, it lacks that ‘d3-feel’ where we can take advantage of selections and their inherent ‘enter/update/exit’ lifecycle. Also, I have yet to determine if it is better to require calls of the ‘render()’ method to redraw the component (in this case, our forcecircle component) or if that should happen anytime a relevant accessor is executed. For example, should an cx/cy update to the circle be done like this:
circle.cx(newX).cy(newY).render();
or like this:
circle.cx(newX).cy(newY);
(second way assumes accessors call render() internally when the values changes)
The second way is cleaner, but results in two calls to the render() method: one for the cx() accessor call and one for the cy() accessor call. I’m hopeful that, over time, we will find a better way to build reusable d3 components. Right now it feels like the more modular things get, the further away we get from using the selections and lifecycles that make d3 so great.
Hi Bill,
I am looking into adding minimap functionality for my existing d3 force layout. I really like your solutions, but i am curious if you know – will it work when my nodes are move-able and use cola.js grouping functionality?
Cheers, Konstantin
It should work fine with any SVG image. I’ve never worked with Cola.js but I suspect it will work fine with any force layer (see my circles example)