Kinetic.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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/BaseTypes/Class.js
  7. * @requires OpenLayers/Animation.js
  8. */
  9. OpenLayers.Kinetic = OpenLayers.Class({
  10. /**
  11. * Property: threshold
  12. * In most cases changing the threshold isn't needed.
  13. * In px/ms, default to 0.
  14. */
  15. threshold: 0,
  16. /**
  17. * Property: deceleration
  18. * {Float} the deseleration in px/ms², default to 0.0035.
  19. */
  20. deceleration: 0.0035,
  21. /**
  22. * Property: nbPoints
  23. * {Integer} the number of points we use to calculate the kinetic
  24. * initial values.
  25. */
  26. nbPoints: 100,
  27. /**
  28. * Property: delay
  29. * {Float} time to consider to calculate the kinetic initial values.
  30. * In ms, default to 200.
  31. */
  32. delay: 200,
  33. /**
  34. * Property: points
  35. * List of points use to calculate the kinetic initial values.
  36. */
  37. points: undefined,
  38. /**
  39. * Property: timerId
  40. * ID of the timer.
  41. */
  42. timerId: undefined,
  43. /**
  44. * Constructor: OpenLayers.Kinetic
  45. *
  46. * Parameters:
  47. * options - {Object}
  48. */
  49. initialize: function(options) {
  50. OpenLayers.Util.extend(this, options);
  51. },
  52. /**
  53. * Method: begin
  54. * Begins the dragging.
  55. */
  56. begin: function() {
  57. OpenLayers.Animation.stop(this.timerId);
  58. this.timerId = undefined;
  59. this.points = [];
  60. },
  61. /**
  62. * Method: update
  63. * Updates during the dragging.
  64. *
  65. * Parameters:
  66. * xy - {<OpenLayers.Pixel>} The new position.
  67. */
  68. update: function(xy) {
  69. this.points.unshift({xy: xy, tick: new Date().getTime()});
  70. if (this.points.length > this.nbPoints) {
  71. this.points.pop();
  72. }
  73. },
  74. /**
  75. * Method: end
  76. * Ends the dragging, start the kinetic.
  77. *
  78. * Parameters:
  79. * xy - {<OpenLayers.Pixel>} The last position.
  80. *
  81. * Returns:
  82. * {Object} An object with two properties: "speed", and "theta". The
  83. * "speed" and "theta" values are to be passed to the move
  84. * function when starting the animation.
  85. */
  86. end: function(xy) {
  87. var last, now = new Date().getTime();
  88. for (var i = 0, l = this.points.length, point; i < l; i++) {
  89. point = this.points[i];
  90. if (now - point.tick > this.delay) {
  91. break;
  92. }
  93. last = point;
  94. }
  95. if (!last) {
  96. return;
  97. }
  98. var time = new Date().getTime() - last.tick;
  99. var dist = Math.sqrt(Math.pow(xy.x - last.xy.x, 2) +
  100. Math.pow(xy.y - last.xy.y, 2));
  101. var speed = dist / time;
  102. if (speed == 0 || speed < this.threshold) {
  103. return;
  104. }
  105. var theta = Math.asin((xy.y - last.xy.y) / dist);
  106. if (last.xy.x <= xy.x) {
  107. theta = Math.PI - theta;
  108. }
  109. return {speed: speed, theta: theta};
  110. },
  111. /**
  112. * Method: move
  113. * Launch the kinetic move pan.
  114. *
  115. * Parameters:
  116. * info - {Object} An object with two properties, "speed", and "theta".
  117. * These values are those returned from the "end" call.
  118. * callback - {Function} Function called on every step of the animation,
  119. * receives x, y (values to pan), end (is the last point).
  120. */
  121. move: function(info, callback) {
  122. var v0 = info.speed;
  123. var fx = Math.cos(info.theta);
  124. var fy = -Math.sin(info.theta);
  125. var initialTime = new Date().getTime();
  126. var lastX = 0;
  127. var lastY = 0;
  128. var timerCallback = function() {
  129. if (this.timerId == null) {
  130. return;
  131. }
  132. var t = new Date().getTime() - initialTime;
  133. var p = (-this.deceleration * Math.pow(t, 2)) / 2.0 + v0 * t;
  134. var x = p * fx;
  135. var y = p * fy;
  136. var args = {};
  137. args.end = false;
  138. var v = -this.deceleration * t + v0;
  139. if (v <= 0) {
  140. OpenLayers.Animation.stop(this.timerId);
  141. this.timerId = null;
  142. args.end = true;
  143. }
  144. args.x = x - lastX;
  145. args.y = y - lastY;
  146. lastX = x;
  147. lastY = y;
  148. callback(args.x, args.y, args.end);
  149. };
  150. this.timerId = OpenLayers.Animation.start(
  151. OpenLayers.Function.bind(timerCallback, this)
  152. );
  153. },
  154. CLASS_NAME: "OpenLayers.Kinetic"
  155. });