From ec291cbeac417d7035eb9e4b248bda5fb3f4a6d4 Mon Sep 17 00:00:00 2001 From: Robert Konigsberg Date: Thu, 27 Jan 2011 12:12:00 -0500 Subject: [PATCH] Fix for issue 112: off-by-one issues with panning. This also fixes an annoying problem with y-axis panning where the closer to the bottom a pan operation, the more severe an initial jagging occurs along the y-axis. The keys to this fix are a) an off-by-one error related to computing widths and heights, and b) the use of the plotter area's dimensions rather than the graph's dimensions (graph dimensions also account for spaces for the tick marks and annotations; that doesn't help us very well.) --- dygraph.js | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/dygraph.js b/dygraph.js index 8741bf0..f1ecd42 100644 --- a/dygraph.js +++ b/dygraph.js @@ -801,6 +801,8 @@ Dygraph.startPan = function(event, g, context) { context.isPanning = true; var xRange = g.xAxisRange(); context.dateRange = xRange[1] - xRange[0]; + context.initialLeftmostDate = xRange[0]; + context.xUnitsPerPixel = context.dateRange / (g.plotter_.area.w - 1); // Record the range of each y-axis at the start of the drag. // If any axis has a valueRange or valueWindow, then we want a 2D pan. @@ -808,15 +810,12 @@ Dygraph.startPan = function(event, g, context) { for (var i = 0; i < g.axes_.length; i++) { var axis = g.axes_[i]; var yRange = g.yAxisRange(i); + // TODO(konigsberg): These values should be in |context|. axis.dragValueRange = yRange[1] - yRange[0]; - var r = g.toDataCoords(null, context.dragStartY, i); - axis.draggingValue = r[1]; + axis.initialTopValue = yRange[1]; + axis.unitsPerPixel = axis.dragValueRange / (g.plotter_.area.h - 1); if (axis.valueWindow || axis.valueRange) context.is2DPan = true; } - - // TODO(konigsberg): Switch from all this math to toDataCoords? - // Seems to work for the dragging value. - context.draggingDate = (context.dragStartX / g.width_) * context.dateRange + xRange[0]; }; // Called in response to an interaction model operation that @@ -830,14 +829,8 @@ Dygraph.movePan = function(event, g, context) { context.dragEndX = g.dragGetX_(event, context); context.dragEndY = g.dragGetY_(event, context); - // TODO(danvk): update this comment - // Want to have it so that: - // 1. draggingDate appears at dragEndX, draggingValue appears at dragEndY. - // 2. daterange = (dateWindow_[1] - dateWindow_[0]) is unaltered. - // 3. draggingValue appears at dragEndY. - // 4. valueRange is unaltered. - - var minDate = context.draggingDate - (context.dragEndX / g.width_) * context.dateRange; + var minDate = context.initialLeftmostDate - + (context.dragEndX - context.dragStartX) * context.xUnitsPerPixel; var maxDate = minDate + context.dateRange; g.dateWindow_ = [minDate, maxDate]; @@ -847,7 +840,8 @@ Dygraph.movePan = function(event, g, context) { var y_frac = context.dragEndY / g.height_; for (var i = 0; i < g.axes_.length; i++) { var axis = g.axes_[i]; - var maxValue = axis.draggingValue + y_frac * axis.dragValueRange; + var maxValue = axis.initialTopValue + + (context.dragEndY - context.dragStartY) * axis.unitsPerPixel; var minValue = maxValue - axis.dragValueRange; axis.valueWindow = [ minValue, maxValue ]; } @@ -864,9 +858,12 @@ Dygraph.movePan = function(event, g, context) { // panning behavior. // Dygraph.endPan = function(event, g, context) { + // TODO(konigsberg): Clear the context data from the axis. + // TODO(konigsberg): mouseup should just delete the + // context object, and mousedown should create a new one. context.isPanning = false; context.is2DPan = false; - context.draggingDate = null; + context.initialLeftmostDate = null; context.dateRange = null; context.valueRange = null; } @@ -1042,12 +1039,12 @@ Dygraph.prototype.createDragInterface_ = function() { prevEndY: null, prevDragDirection: null, - // TODO(danvk): update this comment - // draggingDate and draggingValue represent the [date,value] point on the - // graph at which the mouse was pressed. As the mouse moves while panning, - // the viewport must pan so that the mouse position points to - // [draggingDate, draggingValue] - draggingDate: null, + // The value on the left side of the graph when a pan operation starts. + initialLeftmostDate: null, + + // The number of units each pixel spans. (This won't be valid for log + // scales) + xUnitsPerPixel: null, // TODO(danvk): update this comment // The range in second/value units that the viewport encompasses during a -- 2.7.4