+ c_now = {
+ pageX: 0.5 * (touches[0].pageX + touches[1].pageX),
+ pageY: 0.5 * (touches[0].pageY + touches[1].pageY)
+ };
+ }
+
+ // this is the "swipe" component
+ // we toss it out for now, but could use it in the future.
+ var swipe = {
+ pageX: c_now.pageX - c_init.pageX,
+ pageY: c_now.pageY - c_init.pageY
+ };
+ var dataWidth = context.initialRange.x[1] - context.initialRange.x[0];
+ var dataHeight = context.initialRange.y[0] - context.initialRange.y[1];
+ swipe.dataX = (swipe.pageX / g.plotter_.area.w) * dataWidth;
+ swipe.dataY = (swipe.pageY / g.plotter_.area.h) * dataHeight;
+ var xScale, yScale;
+
+ // The residual bits are usually split into scale & rotate bits, but we split
+ // them into x-scale and y-scale bits.
+ if (touches.length == 1) {
+ xScale = 1.0;
+ yScale = 1.0;
+ } else if (touches.length >= 2) {
+ var initHalfWidth = (initialTouches[1].pageX - c_init.pageX);
+ xScale = (touches[1].pageX - c_now.pageX) / initHalfWidth;
+
+ var initHalfHeight = (initialTouches[1].pageY - c_init.pageY);
+ yScale = (touches[1].pageY - c_now.pageY) / initHalfHeight;
+ }
+
+ // Clip scaling to [1/8, 8] to prevent too much blowup.
+ xScale = Math.min(8, Math.max(0.125, xScale));
+ yScale = Math.min(8, Math.max(0.125, yScale));
+
+ var didZoom = false;
+ if (context.touchDirections.x) {
+ g.dateWindow_ = [
+ c_init.dataX - swipe.dataX + (context.initialRange.x[0] - c_init.dataX) / xScale,
+ c_init.dataX - swipe.dataX + (context.initialRange.x[1] - c_init.dataX) / xScale
+ ];
+ didZoom = true;
+ }
+
+ if (context.touchDirections.y) {
+ for (i = 0; i < 1 /*g.axes_.length*/; i++) {
+ var axis = g.axes_[i];
+ var logscale = g.attributes_.getForAxis("logscale", i);
+ if (logscale) {
+ // TODO(danvk): implement
+ } else {
+ axis.valueWindow = [
+ c_init.dataY - swipe.dataY + (context.initialRange.y[0] - c_init.dataY) / yScale,
+ c_init.dataY - swipe.dataY + (context.initialRange.y[1] - c_init.dataY) / yScale
+ ];
+ didZoom = true;
+ }
+ }
+ }
+
+ g.drawGraph_(false);
+
+ // We only call zoomCallback on zooms, not pans, to mirror desktop behavior.
+ if (didZoom && touches.length > 1 && g.getFunctionOption('zoomCallback')) {
+ var viewWindow = g.xAxisRange();
+ g.getFunctionOption("zoomCallback").call(g, viewWindow[0], viewWindow[1], g.yAxisRanges());