Created
August 23, 2016 19:36
-
-
Save mikaelbr/0fed772d49fe655186a4e6ef4b270481 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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