Pierre
Pierre

Reputation: 943

How to update node style upon zooming?

I would like to change the node style based on its size. In the given example, I would like to color nodes in red the zoom factor is below 0.5, otherwise use the group color. I Tried the following code, but it returns an error message: null is not an object (d3.event.transform). According to the error code, I think d3.event.transform is not yet initialized.

Is there a way to get the zoom factor from within the node style function?

var node = pane.append("g")
    .attr("class", "nodes")
    .selectAll("circle")
    .data(graph.nodes)
    .enter().append("circle")
    .attr("class", "node")
    .attr("r", function(d) { return d.value*5   })
    .style("fill", function(d) {
           return (d3.event.transform.k < 0.5) ? "red": color(d.group);
    });

Upvotes: 0

Views: 205

Answers (2)

Pierre
Pierre

Reputation: 943

I eventually managed to have it working, node.on("zoom", ...) didn't work for me, but its function inside the zoomed function made the trick. I guess nodes never get zoom events, probably because the call(zoom) function is attached to the whole graph.

function zoomed() {
    d3.selectAll('circle').style('fill', function(d) {
        return (d.value > d3.event.transform.k) ? 'red': color(d.group);
    })
    pane.attr("transform", d3.event.transform);
}

Nodes greater than a the zoom scale get colored in red (fiddle here). This may not be the best solution, especially for large graphs, but this work.

Upvotes: 0

Mehdi
Mehdi

Reputation: 7403

The shared code excerpt is not complete, but I guess that this corresponds to the code used at initial generation of the drawing, and it is not wrapped inside a listener of the 'zoom' event.

What should be done is:

  1. initizalize the drawing with the default color
  2. update the fill color on zoom event.

Updated code:

Initialize the drawing:

var node = pane.append("g")
    .attr("class", "nodes")
    .selectAll("circle")
    .data(graph.nodes)
    .enter().append("circle")
    .attr("class", "node")
    .attr("r", function(d) { return d.value*5   })
    .style("fill", function(d) {
           return color(d.group);
    });

Then listen to the zoom event:

node.on('zoom', function() {
    node.selectAll('circle')
      .style('fill', function(d) {
        return (d3.event.transform.k < 0.5) ? 'red': color(d.group);
    })
})

Upvotes: 2

Related Questions