Sina Sohi
Sina Sohi

Reputation: 2779

How to zoom properly using D3.js?

I am trying to make zooming work on my D3 graph.

I have currently found a solution to making my zoom work whilst having an ordinal x-axis, but I have trouble having the x-axis zoom match with the circle and square elements. The more you zoom in, the more "out of place" they become.

Here is a JS fiddle to my current code, where I've attempted to implement my zoom.

http://jsfiddle.net/Vanquiza/c794g977/3/

I would like to know how to properly implement my zoom so that the elements don't go out of place.

Below I've pasted my zoom functions:

var zoom = d3.behavior.zoom()
    .scaleExtent([1, 10])
    .on("zoom", zoomHandler);

function zoomHandler() {
    var translate = zoom.translate(),
    scale = zoom.scale();

    var tx = Math.min(0, Math.max(width * (1 - scale), translate[0]));
    var ty = Math.min(0, Math.max(height * (1 - scale), translate[1]));

    zoom.translate([tx, ty]);

    //svg.select(".x.axis").call(xAxis);
    svg.selectAll(".circleNodes")
        .attr("transform", "translate(" + d3.event.translate[0]+",0)scale(" + d3.event.scale + ",1)");

    svg.selectAll(".squareNodes")
        .attr("transform", "translate(" + d3.event.translate[0]+",0)scale(" + d3.event.scale + ",1)");

    svg.select(".x.axis").attr("transform", "translate(" + d3.event.translate[0]+","+(height)+")")
        .call(xAxis.scale(x.rangeRoundBands([0, (width * d3.event.scale)],1 * d3.event.scale)));

}

Any help is greatly appretiated!

Upvotes: 0

Views: 468

Answers (1)

meetamit
meetamit

Reputation: 25157

Remove the transform altogether. All the adjustments can be done by modifying the ordinal scale, accounting for the translation there.

x.rangeBands([d3.event.translate[0], d3.event.translate[0]+(width * d3.event.scale)], 1)

(Switch to using rangeBands() instead of rangeRoundBands() which eliminates the jitter.)

Then you just have to adjust the positions to all the circles and squares and re-render the axis based on this new scale.

svg.select(".x.axis").call(xAxis)
circle.attr("cx", function(d){ return x(d);})
square.attr("x", function(d){ return x(d) - squareSize/2;})

Here's the working jsFiddle

Upvotes: 2

Related Questions