Tween.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  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. /**
  10. * Namespace: OpenLayers.Tween
  11. */
  12. OpenLayers.Tween = OpenLayers.Class({
  13. /**
  14. * APIProperty: easing
  15. * {<OpenLayers.Easing>(Function)} Easing equation used for the animation
  16. * Defaultly set to OpenLayers.Easing.Expo.easeOut
  17. */
  18. easing: null,
  19. /**
  20. * APIProperty: begin
  21. * {Object} Values to start the animation with
  22. */
  23. begin: null,
  24. /**
  25. * APIProperty: finish
  26. * {Object} Values to finish the animation with
  27. */
  28. finish: null,
  29. /**
  30. * APIProperty: duration
  31. * {int} duration of the tween (number of steps)
  32. */
  33. duration: null,
  34. /**
  35. * APIProperty: callbacks
  36. * {Object} An object with start, eachStep and done properties whose values
  37. * are functions to be call during the animation. They are passed the
  38. * current computed value as argument.
  39. */
  40. callbacks: null,
  41. /**
  42. * Property: time
  43. * {int} Step counter
  44. */
  45. time: null,
  46. /**
  47. * APIProperty: minFrameRate
  48. * {Number} The minimum framerate for animations in frames per second. After
  49. * each step, the time spent in the animation is compared to the calculated
  50. * time at this frame rate. If the animation runs longer than the calculated
  51. * time, the next step is skipped. Default is 30.
  52. */
  53. minFrameRate: null,
  54. /**
  55. * Property: startTime
  56. * {Number} The timestamp of the first execution step. Used for skipping
  57. * frames
  58. */
  59. startTime: null,
  60. /**
  61. * Property: animationId
  62. * {int} Loop id returned by OpenLayers.Animation.start
  63. */
  64. animationId: null,
  65. /**
  66. * Property: playing
  67. * {Boolean} Tells if the easing is currently playing
  68. */
  69. playing: false,
  70. /**
  71. * Constructor: OpenLayers.Tween
  72. * Creates a Tween.
  73. *
  74. * Parameters:
  75. * easing - {<OpenLayers.Easing>(Function)} easing function method to use
  76. */
  77. initialize: function(easing) {
  78. this.easing = (easing) ? easing : OpenLayers.Easing.Expo.easeOut;
  79. },
  80. /**
  81. * APIMethod: start
  82. * Plays the Tween, and calls the callback method on each step
  83. *
  84. * Parameters:
  85. * begin - {Object} values to start the animation with
  86. * finish - {Object} values to finish the animation with
  87. * duration - {int} duration of the tween (number of steps)
  88. * options - {Object} hash of options (callbacks (start, eachStep, done),
  89. * minFrameRate)
  90. */
  91. start: function(begin, finish, duration, options) {
  92. this.playing = true;
  93. this.begin = begin;
  94. this.finish = finish;
  95. this.duration = duration;
  96. this.callbacks = options.callbacks;
  97. this.minFrameRate = options.minFrameRate || 30;
  98. this.time = 0;
  99. this.startTime = new Date().getTime();
  100. OpenLayers.Animation.stop(this.animationId);
  101. this.animationId = null;
  102. if (this.callbacks && this.callbacks.start) {
  103. this.callbacks.start.call(this, this.begin);
  104. }
  105. this.animationId = OpenLayers.Animation.start(
  106. OpenLayers.Function.bind(this.play, this)
  107. );
  108. },
  109. /**
  110. * APIMethod: stop
  111. * Stops the Tween, and calls the done callback
  112. * Doesn't do anything if animation is already finished
  113. */
  114. stop: function() {
  115. if (!this.playing) {
  116. return;
  117. }
  118. if (this.callbacks && this.callbacks.done) {
  119. this.callbacks.done.call(this, this.finish);
  120. }
  121. OpenLayers.Animation.stop(this.animationId);
  122. this.animationId = null;
  123. this.playing = false;
  124. },
  125. /**
  126. * Method: play
  127. * Calls the appropriate easing method
  128. */
  129. play: function() {
  130. var value = {};
  131. for (var i in this.begin) {
  132. var b = this.begin[i];
  133. var f = this.finish[i];
  134. if (b == null || f == null || isNaN(b) || isNaN(f)) {
  135. throw new TypeError('invalid value for Tween');
  136. }
  137. var c = f - b;
  138. value[i] = this.easing.apply(this, [this.time, b, c, this.duration]);
  139. }
  140. this.time++;
  141. if (this.callbacks && this.callbacks.eachStep) {
  142. // skip frames if frame rate drops below threshold
  143. if ((new Date().getTime() - this.startTime) / this.time <= 1000 / this.minFrameRate) {
  144. this.callbacks.eachStep.call(this, value);
  145. }
  146. }
  147. if (this.time > this.duration) {
  148. this.stop();
  149. }
  150. },
  151. /**
  152. * Create empty functions for all easing methods.
  153. */
  154. CLASS_NAME: "OpenLayers.Tween"
  155. });
  156. /**
  157. * Namespace: OpenLayers.Easing
  158. *
  159. * Credits:
  160. * Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>
  161. */
  162. OpenLayers.Easing = {
  163. /**
  164. * Create empty functions for all easing methods.
  165. */
  166. CLASS_NAME: "OpenLayers.Easing"
  167. };
  168. /**
  169. * Namespace: OpenLayers.Easing.Linear
  170. */
  171. OpenLayers.Easing.Linear = {
  172. /**
  173. * Function: easeIn
  174. *
  175. * Parameters:
  176. * t - {Float} time
  177. * b - {Float} beginning position
  178. * c - {Float} total change
  179. * d - {Float} duration of the transition
  180. *
  181. * Returns:
  182. * {Float}
  183. */
  184. easeIn: function(t, b, c, d) {
  185. return c*t/d + b;
  186. },
  187. /**
  188. * Function: easeOut
  189. *
  190. * Parameters:
  191. * t - {Float} time
  192. * b - {Float} beginning position
  193. * c - {Float} total change
  194. * d - {Float} duration of the transition
  195. *
  196. * Returns:
  197. * {Float}
  198. */
  199. easeOut: function(t, b, c, d) {
  200. return c*t/d + b;
  201. },
  202. /**
  203. * Function: easeInOut
  204. *
  205. * Parameters:
  206. * t - {Float} time
  207. * b - {Float} beginning position
  208. * c - {Float} total change
  209. * d - {Float} duration of the transition
  210. *
  211. * Returns:
  212. * {Float}
  213. */
  214. easeInOut: function(t, b, c, d) {
  215. return c*t/d + b;
  216. },
  217. CLASS_NAME: "OpenLayers.Easing.Linear"
  218. };
  219. /**
  220. * Namespace: OpenLayers.Easing.Expo
  221. */
  222. OpenLayers.Easing.Expo = {
  223. /**
  224. * Function: easeIn
  225. *
  226. * Parameters:
  227. * t - {Float} time
  228. * b - {Float} beginning position
  229. * c - {Float} total change
  230. * d - {Float} duration of the transition
  231. *
  232. * Returns:
  233. * {Float}
  234. */
  235. easeIn: function(t, b, c, d) {
  236. return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
  237. },
  238. /**
  239. * Function: easeOut
  240. *
  241. * Parameters:
  242. * t - {Float} time
  243. * b - {Float} beginning position
  244. * c - {Float} total change
  245. * d - {Float} duration of the transition
  246. *
  247. * Returns:
  248. * {Float}
  249. */
  250. easeOut: function(t, b, c, d) {
  251. return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
  252. },
  253. /**
  254. * Function: easeInOut
  255. *
  256. * Parameters:
  257. * t - {Float} time
  258. * b - {Float} beginning position
  259. * c - {Float} total change
  260. * d - {Float} duration of the transition
  261. *
  262. * Returns:
  263. * {Float}
  264. */
  265. easeInOut: function(t, b, c, d) {
  266. if (t==0) return b;
  267. if (t==d) return b+c;
  268. if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
  269. return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
  270. },
  271. CLASS_NAME: "OpenLayers.Easing.Expo"
  272. };
  273. /**
  274. * Namespace: OpenLayers.Easing.Quad
  275. */
  276. OpenLayers.Easing.Quad = {
  277. /**
  278. * Function: easeIn
  279. *
  280. * Parameters:
  281. * t - {Float} time
  282. * b - {Float} beginning position
  283. * c - {Float} total change
  284. * d - {Float} duration of the transition
  285. *
  286. * Returns:
  287. * {Float}
  288. */
  289. easeIn: function(t, b, c, d) {
  290. return c*(t/=d)*t + b;
  291. },
  292. /**
  293. * Function: easeOut
  294. *
  295. * Parameters:
  296. * t - {Float} time
  297. * b - {Float} beginning position
  298. * c - {Float} total change
  299. * d - {Float} duration of the transition
  300. *
  301. * Returns:
  302. * {Float}
  303. */
  304. easeOut: function(t, b, c, d) {
  305. return -c *(t/=d)*(t-2) + b;
  306. },
  307. /**
  308. * Function: easeInOut
  309. *
  310. * Parameters:
  311. * t - {Float} time
  312. * b - {Float} beginning position
  313. * c - {Float} total change
  314. * d - {Float} duration of the transition
  315. *
  316. * Returns:
  317. * {Float}
  318. */
  319. easeInOut: function(t, b, c, d) {
  320. if ((t/=d/2) < 1) return c/2*t*t + b;
  321. return -c/2 * ((--t)*(t-2) - 1) + b;
  322. },
  323. CLASS_NAME: "OpenLayers.Easing.Quad"
  324. };