I\'ve built a d3.js scatter plot with zoom/pan functionality. You can see the full thing here (click \'Open in a new window\' to see the whole thing): http://bl.ocks.org/129
To start with the median function just takes an array and an optional accessor. So you can use it the same way you use max:
var med = d3.median(data, function(d) { return +d.TotalEmployed2011; });
As for the others if you pull out your zoom behaviour you can control it a bit better. So for example instead of
var svg = d3.select()...call(d3.behavior.zoom()...)
try:
var zm = d3.behavior.zoom().x(x).y(y).scaleExtent([1, 8]).on("zoom", zoom);
var svg = d3.select()...call(zm);
Then you can set the zoom level and translation directly:
function zoomIn() {
zm.scale(zm.scale()*2);
// probably need to compute a new translation also
}
function reset() {
zm.scale(1);
zm.translate([0,0]);
}
Restricting the panning range is a bit trickier. You can simply not update when the translate or scale is not to your liking inside you zoom function (or set the zoom's "translate" to what you need it to be). Something like (I think in your case):
function zoom() {
if(y.domain()[0] < 0) {
// To restrict translation to 0 value
zm.translate([d3.event.translate[0], height * (1 - zm.scale())]);
}
....
}
Keep in mind that if you want zooming in to allow a negative on the axis, but panning not to you will find you get into some tricky scenarios.
This might be dated, but check out Limiting domain when zooming or panning in D3.js
Note also that the zoom behaviour did have functionality for limiting panning and zooming at one point. But the code was taken out in a later update.