From 66fb6a6f8aefd3072cc098bf0dcb3a3d1aafccc5 Mon Sep 17 00:00:00 2001 From: Robert Konigsberg Date: Wed, 22 Dec 2010 22:19:29 -0800 Subject: [PATCH] Fix zooming in interaction.js so it focuses on the point where the mouse cursor is. --- tests/interaction.js | 75 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 13 deletions(-) diff --git a/tests/interaction.js b/tests/interaction.js index ab5d5f5..3e72c78 100644 --- a/tests/interaction.js +++ b/tests/interaction.js @@ -23,40 +23,89 @@ } } + // Take the offset of a mouse event on the dygraph canvas and + // convert it to a pair of percentages from the bottom left. + // (Not top left, bottom is where the lower value is.) + function offsetToPercentage(g, offsetX, offsetY) { + // This is calculating the pixel offset of the leftmost date. + var xOffset = g.toDomCoords(g.xAxisRange()[0], null)[0]; + var yar0 = g.yAxisRange(0); + + // This is calculating the pixel of the higest value. (Top pixel) + var yOffset = g.toDomCoords(null, yar0[1])[1]; + + // x y w and h are relative to the corner of the drawing area, + // so that the upper corner of the drawing area is (0, 0). + var x = offsetX - xOffset; + var y = offsetY - yOffset; + + // This is computing the rightmost pixel, effectively defining the + // width. + var w = g.toDomCoords(g.xAxisRange()[1], null)[0] - xOffset; + + // This is computing the lowest pixel, effectively defining the height. + var h = g.toDomCoords(null, yar0[0])[1] - yOffset; + + // Percentage from the left. + var xPct = w == 0 ? 0 : (x / w); + // Percentage from the top. + var yPct = h == 0 ? 0 : (y / h); + + // The (1-) part below changes it from "% distance down from the top" + // to "% distance up from the bottom". + return [xPct, (1-yPct)]; + } + function dblClickV3(event, g, context) { + // Reducing by 20% makes it 80% the original size, which means + // to restore to original size it must grow by 25% + var percentages = offsetToPercentage(g, event.offsetX, event.offsetY); + var xPct = percentages[0]; + var yPct = percentages[1]; + if (event.ctrlKey) { - zoom(g, -(1/8)); + zoom(g, -.25, xPct, yPct); } else { - zoom(g, +.1); + zoom(g, +.2, xPct, yPct); } } function scrollV3(event, g, context) { var normal = event.detail ? event.detail * -1 : event.wheelDelta / 40; // For me the normalized value shows 0.075 for one click. If I took - // that verbatim, it would be a 7.5%. I think I'm gonna take 1/10 of that. - // (double for left and right side) - var percentage = normal / 100; + // that verbatim, it would be a 7.5%. + var percentage = normal / 50; + + var percentages = offsetToPercentage(g, event.offsetX, event.offsetY); + var xPct = percentages[0]; + var yPct = percentages[1]; - zoom(g, percentage); + zoom(g, percentage, xPct, yPct); Dygraph.cancelEvent(event); } - function zoom(g, percentage) { - // Adjusts [x, y] toward each other by percentage% - function adjustAxis(axis, percentage) { + // Adjusts [x, y] toward each other by zoomInPercentage% + // Split it so the left/bottom axis gets xBias/yBias of that change and + // tight/top gets (1-xBias)/(1-yBias) of that change. + // + // If a bias is missing it splits it down the middle. + function zoom(g, zoomInPercentage, xBias, yBias) { + xBias = xBias || 0.5; + yBias = yBias || 0.5; + function adjustAxis(axis, zoomInPercentage, bias) { var delta = axis[1] - axis[0]; - var increment = delta * percentage; - return [ axis[0] + increment, axis[1] - increment ]; + var increment = delta * zoomInPercentage; + var foo = [increment * bias, increment * (1-bias)]; + return [ axis[0] + foo[0], axis[1] - foo[1] ]; } var yAxes = g.yAxisRanges(); var newYAxes = []; for (var i = 0; i < yAxes.length; i++) { - newYAxes[i] = adjustAxis(yAxes[i], percentage); + newYAxes[i] = adjustAxis(yAxes[i], zoomInPercentage, yBias); } g.updateOptions({ - dateWindow: adjustAxis(g.xAxisRange(), percentage), + dateWindow: adjustAxis(g.xAxisRange(), zoomInPercentage, xBias), valueRange: newYAxes[0] }); } -- 2.7.4