Skip to content

Instantly share code, notes, and snippets.

@mikaelbr
Created August 23, 2016 19:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mikaelbr/0fed772d49fe655186a4e6ef4b270481 to your computer and use it in GitHub Desktop.
Save mikaelbr/0fed772d49fe655186a4e6ef4b270481 to your computer and use it in GitHub Desktop.
export default function compass (onChange, onFirst = function () { }) {
let hasListened = false;
OrientationPublisher.init(trigger);
function trigger (...args) {
if (!hasListened) {
onFirst(...args);
hasListened = true;
}
onChange(...args);
}
}
const OrientationPublisher = {
active: false
};
// Setup listener
OrientationPublisher.init = function (onChange) {
if (window.DeviceOrientationEvent && !OrientationPublisher.active) {
window.addEventListener('deviceorientation', OrientationPublisher.orientationChange(onChange), false);
window.addEventListener('compassneedscalibration', function () {
alert('fired Compass needs calibration event');
}, false);
OrientationPublisher.active = true;
// window.addEventListener('orientationchange', function() {
// alert('You flipped your phone: orientation ' + (window.orientation || 0);
// });
}
};
OrientationPublisher.getMode = function () {
var elem = document.documentElement;
return elem && elem.clientWidth / elem.clientHeight < 1.1 ? 'portrait' : 'landscape';
};
OrientationPublisher.cloneEvent = function (e) {
return {
alpha: Number((e.alpha || 0).toFixed(3)),
beta: Number((e.beta || 0).toFixed(3)),
gamma: Number((e.gamma || 0).toFixed(3)),
absolute: Number((e.absolute || 0))
};
};
// Normalize starting values based on OS and browser
OrientationPublisher.normalizers = {
// Firefox rotates counter clockwise
firefox: function (e) {
var normalized = OrientationPublisher.cloneEvent(e);
normalized.alpha = normalized.alpha * -1;
normalized.alpha = normalized.alpha - (window.orientation || 0);
return normalized;
},
// Android stock starts facing West
android_stock: function (e) {
var normalized = OrientationPublisher.cloneEvent(e);
normalized.alpha = (normalized.alpha + 270) % 360;
normalized.alpha = normalized.alpha - (window.orientation || 0);
return normalized;
},
// Android Chrome is good to go
android_chrome: function (e) {
var normalized = OrientationPublisher.cloneEvent(e);
normalized.alpha = normalized.alpha - (window.orientation || 0);
return normalized;
},
// Opera Mobile is good to go
opera: function (e) {
var normalized = OrientationPublisher.cloneEvent(e);
normalized.alpha = normalized.alpha - (window.orientation || 0);
return normalized;
},
// IOS uses a custom property and rotates counter clockwise
ios: function (e) {
var normalized = OrientationPublisher.cloneEvent(e);
if (e.webkitCompassHeading) {
// use the custom IOS property otherwise it will be relative
normalized.alpha = e.webkitCompassHeading;
}
// IOS is counter clockwise
normalized.alpha = normalized.alpha * -1;
normalized.alpha = normalized.alpha - (window.orientation || 0);
return normalized;
},
// for now treat is like Chrome desktop which rotates counter clockwise
unknown: function (e) {
var normalized = OrientationPublisher.cloneEvent(e);
normalized.alpha = normalized.alpha * -1;
return normalized;
}
};
// Parse the user agent to get OS and browser so we know how to normalize values
OrientationPublisher.getNormalizerKey = function (ua) {
var userAgent = ua || window.navigator.userAgent;
// IOS uses a special property
if (userAgent.match(/(iPad|iPhone|iPod)/i)) {
return 'ios';
} else if (userAgent.match(/Firefox/i)) {
return 'firefox';
} else if (userAgent.match(/Opera/i)) {
return 'opera';
} else if (userAgent.match(/Android/i)) {
if (window.chrome) {
return 'android_chrome';
} else {
return 'android_stock';
}
} else {
return 'unknown';
}
};
OrientationPublisher.orientationChange = function (callback) {
return function (e) {
var normalizerKey = OrientationPublisher.getNormalizerKey();
var normalizedValues = OrientationPublisher.normalizers[normalizerKey](e);
// If 'absolute' property is null compass will not work because alpha will be relative to orientation at page load!!
normalizedValues.absolute = normalizedValues.absolute || false;
// Broadcast custom event and normalized values for any subscribers
callback({
orientation: (window.orientation || 0),
normalizerKey: normalizerKey,
raw: OrientationPublisher.cloneEvent(e),
normalized: normalizedValues
});
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment