Skip to content

Instantly share code, notes, and snippets.

@ucavus
Forked from leecrossley/shake.js
Last active November 18, 2018 14:18
Show Gist options
  • Save ucavus/5418463 to your computer and use it in GitHub Desktop.
Save ucavus/5418463 to your computer and use it in GitHub Desktop.
Detect shake gestures in Cordova (Phonegap).
/*
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);
}
};
@mackhowell
Copy link

nm.. works with ios8.

@dandv
Copy link

dandv commented Apr 17, 2015

All the fixes proposed by this plugin have been addressed by the original author, @leecrossley. See https://github.com/leecrossley/cordova-plugin-shake-detection

@ucavus
Copy link
Author

ucavus commented Apr 21, 2015

@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 6 in dimension x and -6 in dimension y will result in a nett movement of 0. 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 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment