/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for * full list of contributors). Published under the 2-clause BSD license. * See license.txt in the OpenLayers distribution or repository for the * full text of the license. */ /** * @requires OpenLayers/Handler.js */ /** * Class: OpenLayers.Handler.Pinch * The pinch handler is used to deal with sequences of browser events related * to pinch gestures. The handler is used by controls that want to know * when a pinch sequence begins, when a pinch is happening, and when it has * finished. * * Controls that use the pinch handler typically construct it with callbacks * for 'start', 'move', and 'done'. Callbacks for these keys are * called when the pinch begins, with each change, and when the pinch is * done. * * Create a new pinch handler with the constructor. * * Inherits from: * - */ OpenLayers.Handler.Pinch = OpenLayers.Class(OpenLayers.Handler, { /** * Property: started * {Boolean} When a touchstart event is received, we want to record it, * but not set 'pinching' until the touchmove get started after * starting. */ started: false, /** * Property: stopDown * {Boolean} Stop propagation of touchstart events from getting to * listeners on the same element. Default is false. */ stopDown: false, /** * Property: pinching * {Boolean} */ pinching: false, /** * Property: last * {Object} Object that store informations related to pinch last touch. */ last: null, /** * Property: start * {Object} Object that store informations related to pinch touchstart. */ start: null, /** * Constructor: OpenLayers.Handler.Pinch * Returns OpenLayers.Handler.Pinch * * Parameters: * control - {} The control that is making use of * this handler. If a handler is being used without a control, the * handlers setMap method must be overridden to deal properly with * the map. * callbacks - {Object} An object containing functions to be called when * the pinch operation start, change, or is finished. The callbacks * should expect to receive an object argument, which contains * information about scale, distance, and position of touch points. * options - {Object} */ /** * Method: touchstart * Handle touchstart events * * Parameters: * evt - {Event} * * Returns: * {Boolean} Let the event propagate. */ touchstart: function(evt) { var propagate = true; this.pinching = false; if (OpenLayers.Event.isMultiTouch(evt)) { this.started = true; this.last = this.start = { distance: this.getDistance(evt.touches), delta: 0, scale: 1 }; this.callback("start", [evt, this.start]); propagate = !this.stopDown; } else if (this.started) { // Some webkit versions send fake single-touch events during // multitouch, which cause the drag handler to trigger return false; } else { this.started = false; this.start = null; this.last = null; } // prevent document dragging OpenLayers.Event.preventDefault(evt); return propagate; }, /** * Method: touchmove * Handle touchmove events * * Parameters: * evt - {Event} * * Returns: * {Boolean} Let the event propagate. */ touchmove: function(evt) { if (this.started && OpenLayers.Event.isMultiTouch(evt)) { this.pinching = true; var current = this.getPinchData(evt); this.callback("move", [evt, current]); this.last = current; // prevent document dragging OpenLayers.Event.stop(evt); } else if (this.started) { // Some webkit versions send fake single-touch events during // multitouch, which cause the drag handler to trigger return false; } return true; }, /** * Method: touchend * Handle touchend events * * Parameters: * evt - {Event} * * Returns: * {Boolean} Let the event propagate. */ touchend: function(evt) { if (this.started && !OpenLayers.Event.isMultiTouch(evt)) { this.started = false; this.pinching = false; this.callback("done", [evt, this.start, this.last]); this.start = null; this.last = null; return false; } return true; }, /** * Method: activate * Activate the handler. * * Returns: * {Boolean} The handler was successfully activated. */ activate: function() { var activated = false; if (OpenLayers.Handler.prototype.activate.apply(this, arguments)) { this.pinching = false; activated = true; } return activated; }, /** * Method: deactivate * Deactivate the handler. * * Returns: * {Boolean} The handler was successfully deactivated. */ deactivate: function() { var deactivated = false; if (OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) { this.started = false; this.pinching = false; this.start = null; this.last = null; deactivated = true; } return deactivated; }, /** * Method: getDistance * Get the distance in pixels between two touches. * * Parameters: * touches - {Array(Object)} * * Returns: * {Number} The distance in pixels. */ getDistance: function(touches) { var t0 = touches[0]; var t1 = touches[1]; return Math.sqrt( Math.pow(t0.olClientX - t1.olClientX, 2) + Math.pow(t0.olClientY - t1.olClientY, 2) ); }, /** * Method: getPinchData * Get informations about the pinch event. * * Parameters: * evt - {Event} * * Returns: * {Object} Object that contains data about the current pinch. */ getPinchData: function(evt) { var distance = this.getDistance(evt.touches); var scale = distance / this.start.distance; return { distance: distance, delta: this.last.distance - distance, scale: scale }; }, CLASS_NAME: "OpenLayers.Handler.Pinch" });