Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to have zooming option in NVD3 charts as like in Highcharts?

I recently started using NVD3 charts and like to have zooming option like Highcharts. Is it possible?

like image 297
user1794400 Avatar asked Nov 02 '12 13:11

user1794400


2 Answers

There is a "Line Chart with View Finder" example that uses nv.models.lineWithFocusChart(). This chart type sports an additional "mini map" below the main chart that you can use to zoom and pan the chart:

See: Line Chart with View Finder

like image 189
Andrea Singh Avatar answered Oct 20 '22 17:10

Andrea Singh


You could apply this function to your nvd3 chart. It does not yield a draggable box to assist zooming like in Highcharts but it allows zooming by mouse scroll as shown here: pan+zoom example. You will have to remove the transitions/delays from nvd3 to achieve smooth zooming. For now, you might have to do this manually by altering the nvd3 source file. There is a discussion about that here.

Here is a jsfiddle.

function addZoom(options) {
// scaleExtent
var scaleExtent = 10;

// parameters
var yAxis       = options.yAxis;
var xAxis       = options.xAxis;
var xDomain     = options.xDomain || xAxis.scale().domain;
var yDomain     = options.yDomain || yAxis.scale().domain;
var redraw      = options.redraw;
var svg         = options.svg;
var discrete    = options.discrete;

// scales
var xScale = xAxis.scale();
var yScale = yAxis.scale();

// min/max boundaries
var x_boundary = xScale.domain().slice();
var y_boundary = yScale.domain().slice();

// create d3 zoom handler
var d3zoom = d3.behavior.zoom();

// fix domain
function fixDomain(domain, boundary) {
    if (discrete) {
        domain[0] = parseInt(domain[0]);
        domain[1] = parseInt(domain[1]);
    }
    domain[0] = Math.min(Math.max(domain[0], boundary[0]), boundary[1] - boundary[1]/scaleExtent);
    domain[1] = Math.max(boundary[0] + boundary[1]/scaleExtent, Math.min(domain[1], boundary[1]));
    return domain;
};

// zoom event handler
function zoomed() {
    yDomain(fixDomain(yScale.domain(), y_boundary));
    xDomain(fixDomain(xScale.domain(), x_boundary));
    redraw();
};

// zoom event handler
function unzoomed() {
    xDomain(x_boundary);
    yDomain(y_boundary);
    redraw();
    d3zoom.scale(1);
    d3zoom.translate([0,0]);
};

// initialize wrapper
d3zoom.x(xScale)
      .y(yScale)
      .scaleExtent([1, scaleExtent])
      .on('zoom', zoomed);

// add handler
svg.call(d3zoom).on('dblclick.zoom', unzoomed);
};

// here chart is your nvd3 model
addZoom({
   xAxis  : chart.xAxis,
   yAxis  : chart.yAxis,
   yDomain: chart.yDomain,
   xDomain: chart.xDomain,
   redraw : function() { chart.update() },
   svg    : svg
});
like image 27
guerler Avatar answered Oct 20 '22 17:10

guerler