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