1

I am trying to create a zoomable chart that has a polylinear x-axis. Everything works as expected if I don't have the polylinear axis. However, when using the polylinear axis the panning (and zooming) is very distorted. If you drag the chart to pan you will see the points and x-axis distortions. The example uses the default D3js zoom behaviour. Any suggestions to get smooth panning/zooming would be appreciated.

I am using transforms to position the elements because I had some issues when specifying the cx and cy values (especially when adding new data to a panned or zoomed chart).

Here is the zoom function:

var onZoom = function () {
                if (d3.event.scale == 1) {  //panning

                } else {   //zooming
                    // don't scale points and lines
                    graph.selectAll(".point")
                        .attr("r", 10 / d3.event.scale)
                        .attr("stroke-width", 1 / d3.event.scale);
                }

    graph.selectAll(".point")
        .attr("transform", function (d) { return "translate(" + xMap(d) + "," + yMap(d) + ")scale(" +     d3.event.scale + ")"; });

    graph.select(".xAxis.axis").call(xAxis);
    graph.select(".yAxis.axis").call(yAxis);
};

See example: https://jsfiddle.net/deanb/spjn8zL7/

Dean
  • 11
  • 1

1 Answers1

0

I found out how to pan/zoom the polylinear axis without distortion.

I figured it out while reading the accepted answer to this question: semantic zooming of force directed graph in d3. "The d3 zoom behaviour object modifies the scales by changing their domain. You could get a similar effect by changing the scale range, since the important part is changing the relationship between domain and range.".

I therefore modified the zoom behaviour to not update the x domain and I update the range in the zoom behaviour:

  // update range in zoom event - leave the domain as is
    x.range(d3.range(xTicks.length)
        .map(function (d) { return (d * xRangeDelta) * d3.event.scale + d3.event.translate[0]; }))

    graph.selectAll(".point")
        .attr("transform", function (d) { return "translate(" + xMap(d) + "," + yMap(d) + ")scale(" + d3.event.scale + ")"; });

    graph.select(".xAxis.axis").call(xAxis);
    graph.select(".yAxis.axis").call(yAxis);

Here is an updated fiddle: https://jsfiddle.net/deanb/hsfsx6b9/1/.

Community
  • 1
  • 1
Dean
  • 11
  • 1