shake.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*
  2. * Author: Alex Gibson
  3. * https://github.com/alexgibson/shake.js
  4. * License: MIT license
  5. */
  6. (function(global, factory) {
  7. if (typeof define === 'function' && define.amd) {
  8. define(function() {
  9. return factory(global, global.document);
  10. });
  11. } else if (typeof module !== 'undefined' && module.exports) {
  12. module.exports = factory(global, global.document);
  13. } else {
  14. global.Shake = factory(global, global.document);
  15. }
  16. } (typeof window !== 'undefined' ? window : this, function (window, document) {
  17. 'use strict';
  18. function Shake(options) {
  19. //feature detect
  20. this.hasDeviceMotion = 'ondevicemotion' in window;
  21. this.options = {
  22. threshold: 15, //default velocity threshold for shake to register
  23. timeout: 1000 //default interval between events
  24. };
  25. if (typeof options === 'object') {
  26. for (var i in options) {
  27. if (options.hasOwnProperty(i)) {
  28. this.options[i] = options[i];
  29. }
  30. }
  31. }
  32. //use date to prevent multiple shakes firing
  33. this.lastTime = new Date();
  34. //accelerometer values
  35. this.lastX = null;
  36. this.lastY = null;
  37. this.lastZ = null;
  38. //create custom event
  39. if (typeof document.CustomEvent === 'function') {
  40. this.event = new document.CustomEvent('shake', {
  41. bubbles: true,
  42. cancelable: true
  43. });
  44. } else if (typeof document.createEvent === 'function') {
  45. this.event = document.createEvent('Event');
  46. this.event.initEvent('shake', true, true);
  47. } else {
  48. return false;
  49. }
  50. }
  51. //reset timer values
  52. Shake.prototype.reset = function () {
  53. this.lastTime = new Date();
  54. this.lastX = null;
  55. this.lastY = null;
  56. this.lastZ = null;
  57. };
  58. //start listening for devicemotion
  59. Shake.prototype.start = function () {
  60. this.reset();
  61. if (this.hasDeviceMotion) {
  62. window.addEventListener('devicemotion', this, false);
  63. }
  64. };
  65. //stop listening for devicemotion
  66. Shake.prototype.stop = function () {
  67. if (this.hasDeviceMotion) {
  68. window.removeEventListener('devicemotion', this, false);
  69. }
  70. this.reset();
  71. };
  72. //calculates if shake did occur
  73. Shake.prototype.devicemotion = function (e) {
  74. var current = e.accelerationIncludingGravity;
  75. var currentTime;
  76. var timeDifference;
  77. var deltaX = 0;
  78. var deltaY = 0;
  79. var deltaZ = 0;
  80. if ((this.lastX === null) && (this.lastY === null) && (this.lastZ === null)) {
  81. this.lastX = current.x;
  82. this.lastY = current.y;
  83. this.lastZ = current.z;
  84. return;
  85. }
  86. deltaX = Math.abs(this.lastX - current.x);
  87. deltaY = Math.abs(this.lastY - current.y);
  88. deltaZ = Math.abs(this.lastZ - current.z);
  89. if (((deltaX > this.options.threshold) && (deltaY > this.options.threshold)) || ((deltaX > this.options.threshold) && (deltaZ > this.options.threshold)) || ((deltaY > this.options.threshold) && (deltaZ > this.options.threshold))) {
  90. //calculate time in milliseconds since last shake registered
  91. currentTime = new Date();
  92. timeDifference = currentTime.getTime() - this.lastTime.getTime();
  93. if (timeDifference > this.options.timeout) {
  94. window.dispatchEvent(this.event);
  95. this.lastTime = new Date();
  96. }
  97. }
  98. this.lastX = current.x;
  99. this.lastY = current.y;
  100. this.lastZ = current.z;
  101. };
  102. //event handler
  103. Shake.prototype.handleEvent = function (e) {
  104. if (typeof (this[e.type]) === 'function') {
  105. return this[e.type](e);
  106. }
  107. };
  108. return Shake;
  109. }));