KineticScrolling.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /**
  2. * Phaser Kinetic Scrolling Plugin
  3. * @author Juan Nicholls <jdnichollsc@hotmail.com>
  4. * @copyright 2015 Juan Nicholls - http://jdnichollsc.github.io/Phaser-Kinetic-Scrolling-Plugin/
  5. * @license {@link http://opensource.org/licenses/MIT}
  6. * @version 0.1.2
  7. */
  8. (function (Phaser) {
  9. 'use strict';
  10. /**
  11. * Kinetic Scrolling is a Phaser plugin that allows vertical and horizontal scrolling with kinetic motion.
  12. * It works with the Phaser.Camera
  13. *
  14. * @class Phaser.Plugin.KineticScrolling
  15. * @constructor
  16. * @param {Object} game - The Game object is the instance of the game, where the magic happens.
  17. * @param {Any} parent - The object that owns this plugin, usually Phaser.PluginManager.
  18. */
  19. Phaser.Plugin.KineticScrolling = function (game, parent) {
  20. Phaser.Plugin.call(this, game, parent);
  21. this.dragging = false;
  22. this.timestamp = 0;
  23. this.callbackID = 0;
  24. this.targetX = 0;
  25. this.targetY = 0;
  26. this.autoScrollX = false;
  27. this.autoScrollY = false;
  28. this.startX = 0;
  29. this.startY = 0;
  30. this.velocityX = 0;
  31. this.velocityY = 0;
  32. this.amplitudeX = 0;
  33. this.amplitudeY = 0;
  34. this.directionWheel = 0;
  35. this.velocityWheelX = 0;
  36. this.velocityWheelY = 0;
  37. this.settings = {
  38. kineticMovement: true,
  39. timeConstantScroll: 325, //really mimic iOS
  40. horizontalScroll: true,
  41. verticalScroll: false,
  42. horizontalWheel: true,
  43. verticalWheel: false,
  44. deltaWheel: 40
  45. };
  46. };
  47. Phaser.Plugin.KineticScrolling.prototype = Object.create(Phaser.Plugin.prototype);
  48. Phaser.Plugin.KineticScrolling.prototype.constructor = Phaser.Plugin.KineticScrolling;
  49. /**
  50. * Change Default Settings of the plugin
  51. *
  52. * @method Phaser.Plugin.KineticScrolling#configure
  53. * @param {Object} [options] - Object that contain properties to change the behavior of the plugin.
  54. * @param {number} [options.timeConstantScroll=325] - The rate of deceleration for the scrolling.
  55. * @param {boolean} [options.kineticMovement=true] - Enable or Disable the kinematic motion.
  56. * @param {boolean} [options.horizontalScroll=true] - Enable or Disable the horizontal scrolling.
  57. * @param {boolean} [options.verticalScroll=false] - Enable or Disable the vertical scrolling.
  58. * @param {boolean} [options.horizontalWheel=true] - Enable or Disable the horizontal scrolling with mouse wheel.
  59. * @param {boolean} [options.verticalWheel=false] - Enable or Disable the vertical scrolling with mouse wheel.
  60. * @param {number} [options.deltaWheel=40] - Delta increment of the mouse wheel.
  61. */
  62. Phaser.Plugin.KineticScrolling.prototype.configure = function (options) {
  63. if (options) {
  64. for (var property in options) {
  65. if (this.settings.hasOwnProperty(property)) {
  66. this.settings[property] = options[property];
  67. }
  68. }
  69. }
  70. };
  71. /**
  72. * Start the Plugin.
  73. *
  74. * @method Phaser.Plugin.KineticScrolling#start
  75. */
  76. Phaser.Plugin.KineticScrolling.prototype.start = function () {
  77. this.game.input.onDown.add(this.beginMove, this);
  78. this.callbackID = this.game.input.addMoveCallback(this.moveCamera, this);
  79. this.game.input.onUp.add(this.endMove, this);
  80. this.game.input.mouse.mouseWheelCallback = this.mouseWheel.bind(this);
  81. };
  82. /**
  83. * Event triggered when a pointer is pressed down, resets the value of variables.
  84. */
  85. Phaser.Plugin.KineticScrolling.prototype.beginMove = function () {
  86. this.startX = this.game.input.x;
  87. this.startY = this.game.input.y;
  88. this.dragging = true;
  89. this.timestamp = Date.now();
  90. this.velocityY = this.amplitudeY = this.velocityX = this.amplitudeX = 0;
  91. };
  92. /**
  93. * Event triggered when the activePointer receives a DOM move event such as a mousemove or touchmove.
  94. * The camera moves according to the movement of the pointer, calculating the velocity.
  95. */
  96. Phaser.Plugin.KineticScrolling.prototype.moveCamera = function (pointer, x, y) {
  97. if (!this.dragging) return;
  98. this.now = Date.now();
  99. var elapsed = this.now - this.timestamp;
  100. this.timestamp = this.now;
  101. if (this.settings.horizontalScroll) {
  102. var delta = x - this.startX; //Compute move distance
  103. this.startX = x;
  104. this.velocityX = 0.8 * (1000 * delta / (1 + elapsed)) + 0.2 * this.velocityX;
  105. this.game.camera.x -= delta;
  106. }
  107. if (this.settings.verticalScroll) {
  108. var delta = y - this.startY; //Compute move distance
  109. this.startY = y;
  110. this.velocityY = 0.8 * (1000 * delta / (1 + elapsed)) + 0.2 * this.velocityY;
  111. this.game.camera.y -= delta;
  112. }
  113. };
  114. /**
  115. * Event triggered when a pointer is released, calculates the automatic scrolling.
  116. */
  117. Phaser.Plugin.KineticScrolling.prototype.endMove = function () {
  118. this.dragging = false;
  119. this.autoScrollX = false;
  120. this.autoScrollY = false;
  121. if (!this.settings.kineticMovement) return;
  122. this.now = Date.now();
  123. if (this.velocityX > 10 || this.velocityX < -10) {
  124. this.amplitudeX = 0.8 * this.velocityX;
  125. this.targetX = Math.round(this.game.camera.x - this.amplitudeX);
  126. this.autoScrollX = true;
  127. }
  128. if (this.velocityY > 10 || this.velocityY < -10) {
  129. this.amplitudeY = 0.8 * this.velocityY;
  130. this.targetY = Math.round(this.game.camera.y - this.amplitudeY);
  131. this.autoScrollY = true;
  132. }
  133. };
  134. /**
  135. * Event called after all the core subsystems and the State have updated, but before the render.
  136. * Create the deceleration effect.
  137. */
  138. Phaser.Plugin.KineticScrolling.prototype.update = function () {
  139. this.elapsed = Date.now() - this.timestamp;
  140. if (this.autoScrollX && this.amplitudeX != 0) {
  141. var delta = -this.amplitudeX * Math.exp(-this.elapsed / this.settings.timeConstantScroll);
  142. if (delta > 0.5 || delta < -0.5) {
  143. this.game.camera.x = this.targetX - delta;
  144. }
  145. else {
  146. this.autoScrollX = false;
  147. this.game.camera.x = this.targetX;
  148. }
  149. }
  150. if (this.autoScrollY && this.amplitudeY != 0) {
  151. var delta = -this.amplitudeY * Math.exp(-this.elapsed / this.settings.timeConstantScroll);
  152. if (delta > 0.5 || delta < -0.5) {
  153. this.game.camera.y = this.targetY - delta;
  154. }
  155. else {
  156. this.autoScrollY = false;
  157. this.game.camera.y = this.targetY;
  158. }
  159. }
  160. if (this.settings.horizontalWheel && (this.velocityWheelX < -0.1 || this.velocityWheelX > 0.1)) {
  161. this.game.camera.x -= this.velocityWheelX;
  162. this.velocityWheelX *= 0.95;
  163. }
  164. if (this.settings.verticalWheel && (this.velocityWheelY < -0.1 || this.velocityWheelY > 0.1)) {
  165. this.game.camera.y -= this.velocityWheelY;
  166. this.velocityWheelY *= 0.95;
  167. }
  168. };
  169. /**
  170. * Event called when the mousewheel is used, affect the direction of scrolling.
  171. */
  172. Phaser.Plugin.KineticScrolling.prototype.mouseWheel = function (event) {
  173. if (!this.settings.horizontalWheel && !this.settings.verticalWheel) return;
  174. event.preventDefault();
  175. var delta = this.game.input.mouse.wheelDelta * 120 / this.settings.deltaWheel;
  176. if (this.directionWheel != this.game.input.mouse.wheelDelta) {
  177. this.velocityWheelX = 0;
  178. this.velocityWheelY = 0;
  179. this.directionWheel = this.game.input.mouse.wheelDelta;
  180. }
  181. if (this.settings.horizontalWheel) {
  182. this.autoScrollX = false;
  183. this.velocityWheelX += delta;
  184. }
  185. if (this.settings.verticalWheel) {
  186. this.autoScrollY = false;
  187. this.velocityWheelY += delta;
  188. }
  189. };
  190. /**
  191. * Stop the Plugin.
  192. *
  193. * @method Phaser.Plugin.KineticScrolling#stop
  194. */
  195. Phaser.Plugin.KineticScrolling.prototype.stop = function () {
  196. this.game.input.onDown.remove(this.beginMove, this);
  197. this.game.input.deleteMoveCallback(this.callbackID);
  198. this.game.input.onUp.remove(this.endMove, this);
  199. this.game.input.mouse.mouseWheelCallback = null;
  200. };
  201. } (Phaser));