Zooming, scrolling, and panning of charts is a more complex task than than one might expect due to the little-known fact that Dojo Charting can stack multiple plots per chart and can show multiple independent axes on all 4 sides of the chart. These problems were solved with the following API in the chart object:

  • chart.setAxisWindow(name, scale, offset) — defines a window on the named axis with a scale factor, which starts at the set offset in data coordinates.
    • The scale parameter must be >= 1.
    • The offset parameter should be >= 0.
    • For example if there is an array of 10 numeric values, and 3-8 should show, chart.setWindow(“x”, 3, 2) will do the trick.
    • This call affects only plots attached to the named axis, other plots are unaffected.
  • chart.setWindow(sx, sy, dx, dy) — sets scale and offsets on all plots of the chart.
    • The sx parameter specifies the magnification factor on horizontal axes. It should be >= 1.
    • The sy parameter specifies the magnification factor on vertical axes. It should be >= 1.
    • The dx parameter specifies the offset of horizontal axes in pixels. It should be >= 0.
    • The dy parameter specifies the offset of vertical axes in pixels. It should be >= 0.
    • All chart’s axes (and, by extension, plots) will be affected.

Obviously these new methods do sanity checks, and don’t allow you to scroll outside of axis’ boundaries, or zoom out too far.

As you can see these methods are enough to implement arbitrary zooming to drill down to the smallest details of your chart, scrolling, and panning (moving the chart with your mouse in two dimensions). The latter functionality is taxing on old IE, but modern browsers are well up to the task.

Now it is time for some show-and-tell. Below you can see a test chart in its normal state:

normal

As you can see this chart has four independent axes on all sides, and two plots, each with independent axes: the light brown plot uses the bottom and the the left axis, while the dark brown plot uses the axis on the top and the right sides.

You can access this test application in Dojo Nightlies. Warning: this link uses the raw Dojo served directly from the development server, so the initial loading will be relatively slow. In real applications you should use Dojo builds.

This is the code required to build this chart:

require([
	"dojox/charting/Chart",
	"dojox/charting/plot2d/Areas",
	"dojox/charting/plot2d/Grid",
	"dojox/charting/themes/PlotKit/orange",
	"dojox/charting/axis2d/Default",
	"dojo/domReady!"
	],
	function (Chart, Areas, Grid, PlotKitOrange) {
		// Create the chart
		var chart = new Chart("chartNode");

		// set a theme
		chart.setTheme(PlotKitOrange);

		// create the ordinal horizontal axis with custom visual attributes,
		// by default it will be attached to the bottom of the plot area
		chart.addAxis("x", {
			fixLower: "minor", natural: true, stroke: "grey",
			majorTick: {stroke: "black", length: 4},
			minorTick: {stroke: "gray", length: 2}
		});

		// create the ordinal vertical axis with custom visual attributes,
		// by default it will be attached to the left of the plot area
		chart.addAxis("y", {
			vertical: true, min: 0, max: 30,
			majorTickStep: 5, minorTickStep: 1, stroke: "grey",
			majorTick: {stroke: "black", length: 4},
			minorTick: {stroke: "gray", length: 2}
		});

		// add the front plot, which uses default axes (named "x" and "y")
		chart.addPlot("default", {type: "Areas"});

		// add series to the default plot
		chart.addSeries("Series A",
			[0, 25, 5, 20, 10, 15, 5, 20, 0, 25]
		);

		// create the ordinal horizontal axis with custom visual attributes,
		// we specify explicitly that it should be attached to the top
		chart.addAxis("x2", {
			fixLower: "minor", natural: true,
			leftBottom: false, stroke: "grey",
			majorTick: {stroke: "black", length: 4},
			minorTick: {stroke: "gray", length: 2}
		});

		// create the ordinal vertical axis with custom visual attributes,
		// we specify explicitly that it should be attached to the right
		chart.addAxis("y2", {
			vertical: true, min: 0, max: 20,
			leftBottom: false, stroke: "grey",
			majorTick: {stroke: "black", length: 4},
			minorTick: {stroke: "gray", length: 2}
		});

		// create the back plot, which uses our custom axes ("x2" and "y2")
		chart.addPlot("plot2", {
			type: "Areas", hAxis: "x2", vAxis: "y2"
		});

		// add series to "plot2" we just created
		chart.addSeries("Series B",
			[15, 0, 15, 0, 15, 0, 15, 0, 15,
				0, 15, 0, 15, 0, 15, 0, 15],
			{plot: "plot2"}
		);

		// add the bottom of our stack we put the grid
		// that shows major lines, and horizontal minor lines
		chart.addPlot("grid", {type: "Grid", hMinorLines: true});

		// show what we've built
		chart.render();

Now let’s see it magnified by 2 in both dimensions and moved so we can see the peaks in the middle-left part of the chart:

zoomed

This picture above was made from the previous picture with one call:

chart.setWindow(2, 2, 181, 143).render();

Obviously axes show new labels to reflect the new state of the chart. Using these labels we can get our bearings and understand what we are seeing.

If we want to return back we can always do:

chart.setWindow(1, 1, 0, 0).render();

Further Reading