Pinch.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
  2. * full list of contributors). Published under the 2-clause BSD license.
  3. * See license.txt in the OpenLayers distribution or repository for the
  4. * full text of the license. */
  5. /**
  6. * @requires OpenLayers/Handler.js
  7. */
  8. /**
  9. * Class: OpenLayers.Handler.Pinch
  10. * The pinch handler is used to deal with sequences of browser events related
  11. * to pinch gestures. The handler is used by controls that want to know
  12. * when a pinch sequence begins, when a pinch is happening, and when it has
  13. * finished.
  14. *
  15. * Controls that use the pinch handler typically construct it with callbacks
  16. * for 'start', 'move', and 'done'. Callbacks for these keys are
  17. * called when the pinch begins, with each change, and when the pinch is
  18. * done.
  19. *
  20. * Create a new pinch handler with the <OpenLayers.Handler.Pinch> constructor.
  21. *
  22. * Inherits from:
  23. * - <OpenLayers.Handler>
  24. */
  25. OpenLayers.Handler.Pinch = OpenLayers.Class(OpenLayers.Handler, {
  26. /**
  27. * Property: started
  28. * {Boolean} When a touchstart event is received, we want to record it,
  29. * but not set 'pinching' until the touchmove get started after
  30. * starting.
  31. */
  32. started: false,
  33. /**
  34. * Property: stopDown
  35. * {Boolean} Stop propagation of touchstart events from getting to
  36. * listeners on the same element. Default is false.
  37. */
  38. stopDown: false,
  39. /**
  40. * Property: pinching
  41. * {Boolean}
  42. */
  43. pinching: false,
  44. /**
  45. * Property: last
  46. * {Object} Object that store informations related to pinch last touch.
  47. */
  48. last: null,
  49. /**
  50. * Property: start
  51. * {Object} Object that store informations related to pinch touchstart.
  52. */
  53. start: null,
  54. /**
  55. * Constructor: OpenLayers.Handler.Pinch
  56. * Returns OpenLayers.Handler.Pinch
  57. *
  58. * Parameters:
  59. * control - {<OpenLayers.Control>} The control that is making use of
  60. * this handler. If a handler is being used without a control, the
  61. * handlers setMap method must be overridden to deal properly with
  62. * the map.
  63. * callbacks - {Object} An object containing functions to be called when
  64. * the pinch operation start, change, or is finished. The callbacks
  65. * should expect to receive an object argument, which contains
  66. * information about scale, distance, and position of touch points.
  67. * options - {Object}
  68. */
  69. /**
  70. * Method: touchstart
  71. * Handle touchstart events
  72. *
  73. * Parameters:
  74. * evt - {Event}
  75. *
  76. * Returns:
  77. * {Boolean} Let the event propagate.
  78. */
  79. touchstart: function(evt) {
  80. var propagate = true;
  81. this.pinching = false;
  82. if (OpenLayers.Event.isMultiTouch(evt)) {
  83. this.started = true;
  84. this.last = this.start = {
  85. distance: this.getDistance(evt.touches),
  86. delta: 0,
  87. scale: 1
  88. };
  89. this.callback("start", [evt, this.start]);
  90. propagate = !this.stopDown;
  91. } else if (this.started) {
  92. // Some webkit versions send fake single-touch events during
  93. // multitouch, which cause the drag handler to trigger
  94. return false;
  95. } else {
  96. this.started = false;
  97. this.start = null;
  98. this.last = null;
  99. }
  100. // prevent document dragging
  101. OpenLayers.Event.preventDefault(evt);
  102. return propagate;
  103. },
  104. /**
  105. * Method: touchmove
  106. * Handle touchmove events
  107. *
  108. * Parameters:
  109. * evt - {Event}
  110. *
  111. * Returns:
  112. * {Boolean} Let the event propagate.
  113. */
  114. touchmove: function(evt) {
  115. if (this.started && OpenLayers.Event.isMultiTouch(evt)) {
  116. this.pinching = true;
  117. var current = this.getPinchData(evt);
  118. this.callback("move", [evt, current]);
  119. this.last = current;
  120. // prevent document dragging
  121. OpenLayers.Event.stop(evt);
  122. } else if (this.started) {
  123. // Some webkit versions send fake single-touch events during
  124. // multitouch, which cause the drag handler to trigger
  125. return false;
  126. }
  127. return true;
  128. },
  129. /**
  130. * Method: touchend
  131. * Handle touchend events
  132. *
  133. * Parameters:
  134. * evt - {Event}
  135. *
  136. * Returns:
  137. * {Boolean} Let the event propagate.
  138. */
  139. touchend: function(evt) {
  140. if (this.started && !OpenLayers.Event.isMultiTouch(evt)) {
  141. this.started = false;
  142. this.pinching = false;
  143. this.callback("done", [evt, this.start, this.last]);
  144. this.start = null;
  145. this.last = null;
  146. return false;
  147. }
  148. return true;
  149. },
  150. /**
  151. * Method: activate
  152. * Activate the handler.
  153. *
  154. * Returns:
  155. * {Boolean} The handler was successfully activated.
  156. */
  157. activate: function() {
  158. var activated = false;
  159. if (OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
  160. this.pinching = false;
  161. activated = true;
  162. }
  163. return activated;
  164. },
  165. /**
  166. * Method: deactivate
  167. * Deactivate the handler.
  168. *
  169. * Returns:
  170. * {Boolean} The handler was successfully deactivated.
  171. */
  172. deactivate: function() {
  173. var deactivated = false;
  174. if (OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
  175. this.started = false;
  176. this.pinching = false;
  177. this.start = null;
  178. this.last = null;
  179. deactivated = true;
  180. }
  181. return deactivated;
  182. },
  183. /**
  184. * Method: getDistance
  185. * Get the distance in pixels between two touches.
  186. *
  187. * Parameters:
  188. * touches - {Array(Object)}
  189. *
  190. * Returns:
  191. * {Number} The distance in pixels.
  192. */
  193. getDistance: function(touches) {
  194. var t0 = touches[0];
  195. var t1 = touches[1];
  196. return Math.sqrt(
  197. Math.pow(t0.olClientX - t1.olClientX, 2) +
  198. Math.pow(t0.olClientY - t1.olClientY, 2)
  199. );
  200. },
  201. /**
  202. * Method: getPinchData
  203. * Get informations about the pinch event.
  204. *
  205. * Parameters:
  206. * evt - {Event}
  207. *
  208. * Returns:
  209. * {Object} Object that contains data about the current pinch.
  210. */
  211. getPinchData: function(evt) {
  212. var distance = this.getDistance(evt.touches);
  213. var scale = distance / this.start.distance;
  214. return {
  215. distance: distance,
  216. delta: this.last.distance - distance,
  217. scale: scale
  218. };
  219. },
  220. CLASS_NAME: "OpenLayers.Handler.Pinch"
  221. });