-
-
Save ucavus/5418463 to your computer and use it in GitHub Desktop.
/* | |
The only required option is the "success" callback. Usage: | |
var shake = new Shake({ | |
frequency: 300, //milliseconds between polls for accelerometer data. | |
waitBetweenShakes: 1000, //milliseconds to wait before watching for more shake events. | |
threshold: 12, //how hard the shake has to be to register. | |
success: function(magnitude, accelerationDelta, timestamp) {}, //callback when shake is detected. "this" will be the "shake" object. | |
failure: function() {}, //callback when watching/getting acceleration fails. "this" will be the "shake" object. | |
}); | |
shake.startWatch(); | |
shake.stopWatch(); | |
*/ | |
function Shake(options) { | |
var shake = this, | |
watchId = null, | |
defaultOptions = { | |
frequency: 300, | |
waitBetweenShakes: 1000, | |
threshold: 12, | |
success: undefined, | |
failure: undefined | |
}, | |
previousAcceleration; | |
for (var p in defaultOptions) | |
if (!options.hasOwnProperty(p)) | |
options[p] = defaultOptions[p]; | |
// Start watching the accelerometer for a shake gesture | |
shake.startWatch = function () { | |
if (watchId) | |
return; | |
watchId = navigator.accelerometer.watchAcceleration(getAccelerationSnapshot, handleError, { | |
frequency: options.frequency | |
}); | |
}; | |
// Stop watching the accelerometer for a shake gesture | |
shake.stopWatch = function () { | |
if (!watchId) | |
return; | |
navigator.accelerometer.clearWatch(watchId); | |
watchId = null; | |
}; | |
// Gets the current acceleration snapshot from the last accelerometer watch | |
function getAccelerationSnapshot() { | |
navigator.accelerometer.getCurrentAcceleration(assessCurrentAcceleration, handleError); | |
} | |
// Assess the current acceleration parameters to determine a shake | |
function assessCurrentAcceleration(acceleration) { | |
if (!previousAcceleration) { | |
previousAcceleration = acceleration; | |
return; | |
} | |
var accelerationDelta = { | |
x: acceleration.x - previousAcceleration.x, | |
y: acceleration.y - previousAcceleration.y, | |
z: acceleration.z - previousAcceleration.z | |
}; | |
var magnitude = Math.sqrt( | |
Math.pow(accelerationDelta.x, 2) + | |
Math.pow(accelerationDelta.y, 2) + | |
Math.pow(accelerationDelta.z, 2) | |
); | |
if (magnitude >= options.threshold) { | |
// Shake detected | |
if (options.waitBetweenShakes > 0) { | |
shake.stopWatch(); | |
previousAcceleration = undefined; | |
} | |
options.success.call(shake, magnitude, accelerationDelta, acceleration.timestamp); | |
if (options.waitBetweenShakes > 0) | |
setTimeout( | |
function() { | |
shake.startWatch(); | |
}, | |
options.waitBetweenShakes | |
); | |
} | |
else | |
previousAcceleration = acceleration; | |
} | |
// Handle errors here | |
function handleError() { | |
if (options.failure) | |
options.failure.call(shake); | |
} | |
}; |
As a heads-up, neither this nor the original seem to be compatible with iOS 8. :'(
(at least I'm guessing that's the weakest link on my end)
hey @ucavus and @rubencodes can you confirm if/how this is now broken in os 8+?
nm.. works with ios8.
All the fixes proposed by this plugin have been addressed by the original author, @leecrossley. See https://github.com/leecrossley/cordova-plugin-shake-detection
@dandv Not so. The main issue that prompted me to fork in the first place is still not right. Lee apparently does not know how to get a 3d vector's magnitude. In his code, a move of His does not provide any way to use the error handling function without modifying the plugin. It will also fire shake events continuously which is not what I wanted (see my 6
in dimension x
and -6
in dimension y
will result in a nett movement of 0
.waitBetweenShakes
option). It's nice that it's been Cordova-ised, but I wouldn't use it.
Edit: I was wrong about the nett movement bit, but it's still not getting the magnitude correctly. I'm just not a fan of that shake detection logic.
dannythunder, because you called "shake.stopWatch" after you start it.