Kinetic.js 4.8 KB

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