I am using d3 to render a simplified gantt chart, with panning and zooming using d3.behavior.zoom.
The x scale is a time scale (slightly modified to center calendar days in columns, etc) and works beatifully, but I'm having problems deciding how to zoom/pan the y scale, whose domain is a list of tasks which will often be too many to fit in the chart area, so the need for panning/zooming.
Is there a way to tell the default ordinal scale to react to zoom/pan events, or should I write a custom scale? And if I need to write a custom scale, would it be better to base it on d3.scale.ordinal (having it store the whole list of tasks, and use only the visible subset as its domain), or on d3.scale.linear (and then implement something similar to the ordinal scale for rangebands etc?).
Or is there something I'm missing (entirely probable as it's my first project using d3)?
Expanding slightly from my previous answer as I have been contacted privately to explain how I did this.
First, a screenshot of the app in question, whos emain job is aggregating and displaying planning data gathered from various sources (PowerPoint files, corporate databases, etc.).
The relevant bit is the right vertical axis with the colored dots, where each dot represents a project's effort and involved organization. The gray area on the axis is a d3.js brush, and can be panned/resized to change the chart/table data in real time.
// the axis is a regular ordinal axis, with a brush
y2 = d3.scale.ordinal(),
brush = d3.svg.brush().y(y2).on('brush', brushReact),
// [...]
// brush event handler
function brushReact() {
if (tasksSlice == null)
return;
var yrb = y2.rangeBand(),
extent = brush.extent(),
s0 = Math.round(extent[0]/yrb),
s1 = Math.round(extent[1]/yrb);
if (s0 == tasksSlice[0] && s1 == tasksSlice[1])
return;
tasksSlice = [s0, s1];
inner.refresh();
}
What happens inside the handler is pretty simple:
I hope this clears it up.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With