Nihar Sarangi
Nihar Sarangi

Reputation: 4945

How to zoom a chart in d3 correctly?

I am trying to add zoom to a linechart in d3.

var zoom = d3.behavior.zoom()
   .x(xScale)
   .y(yScale)
   .scaleExtent([1, 10])
   .on("zoom", zoomed);
element.call(zoom);

function zoomed() {
   element.attr("transform", "scale(" + d3.event.scale + ")")
    .select(".x.d3-axis").attr('transform', 'translate(0,' + height + ')').call(xAxis)
     .select(".y.d3-axis").attr('transform', 'translate(0,0)').call(yAxis);
    };

jsFiddle

However, each time the chart is zoomed, it moves to the left. I can't seem to find a way to bring it back to the original position when zoom action is done.

How can I fix this?

Upvotes: 0

Views: 838

Answers (1)

Himmel
Himmel

Reputation: 3709

You have to translate your element, in addition to scaling it. Right now, your zoom function is only scaling element.

By changing the transform to include d3.event.translate, you will get the desired behavior.

function zoomed() {
  element
  .attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")")

  ...
}

Here is your fiddle with the updated code.


Update

To get rid of the strange offsets, just add your margin to the d3.event.translate values:

var translate = [d3.event.translate[0] + margin.left, d3.event.translate[1] + margin.top];

element
      .attr("transform", "translate(" + translate + ")scale(" + d3.event.scale + ")")

fiddle

In addition, if you want to make sure that the SVG only stays within the original borders (no overflow), you should check out the SVG clipPath element.

Upvotes: 1

Related Questions