gyrollax
Version:
Add depth to your pages using device sensors and the parallax effect
168 lines (145 loc) • 4.63 kB
JavaScript
var TiltProvider = function() {
var smoothRef = 0.988;
var refAlpha;
var refBeta;
var lastAlpha;
var stableAlpha;
var landscape = false;
var debug = false;
var listener;
return {
start: function(cb) {
window.addEventListener("orientationchange", function(e) {
landscape = (window.orientation != 0);
if(debug) $('#landscape').text(landscape);
});
listener = function(e) {
if(!e.webkitCompassHeading) return; // Compass takes a second to init
if(!e.alpha) return;
if(!e.beta) return;
if(!e.gamma) return;
var alpha = 360 - e.webkitCompassHeading;
var beta = landscape ? -e.gamma : e.beta;
var gamma = landscape ? e.beta : e.gamma;
if(lastAlpha == undefined) {
lastAlpha = alpha;
stableAlpha = alpha;
refAlpha = alpha;
refBeta = beta;
} else {
// 0 -> 360
if(lastAlpha - alpha < -180) {
stableAlpha -= lastAlpha + (360 - alpha);
// 360 -> 0
} else if(lastAlpha - alpha > 180) {
stableAlpha += (360 - lastAlpha) + alpha;
// Regular movement
} else {
stableAlpha += alpha - lastAlpha;
}
lastAlpha = alpha;
refAlpha = refAlpha * smoothRef + stableAlpha * (1 - smoothRef);
refBeta = refBeta * smoothRef + beta * (1 - smoothRef);
var diffAlpha = stableAlpha - refAlpha;
var diffBeta = beta - refBeta;
var uprightness = Math.abs(beta) / 90;
var tilt = ((gamma / 360) + (diffAlpha / 360 / 2)) * (1 - uprightness) + (diffAlpha / 360) * uprightness;
cb(tilt, diffBeta / 360);
if(debug) {
$('#alpha').text(alpha); // 0 - 360
$('#beta').text(beta); // 0 - 90, 0 - -90
$('#gamma').text(gamma); // 0 - -180, 0 - 180
$('#compass').text(e.webkitCompassHeading);
$('#stable-alpha').text(stableAlpha);
$('#refAlpha').text(refAlpha);
$('#refBeta').text(refBeta);
$('#diffAlpha').text(diffAlpha);
$('#diffBeta').text(diffBeta);
$('#uprightness').text(uprightness);
$('#tilt').text(tilt);
}
}
};
window.addEventListener("deviceorientation", listener);
},
stop: function() {
window.removeEventListener(listener);
}
}
};
var SmoothTiltProvider = function() {
var smooth = 0.5;
var running = false;
var tiltX;
var tiltY;
var x = 0;
var y = 0;
var provider = TiltProvider();
return {
start: function(cb) {
provider.start(function(tx, ty) {
tiltX = tx;
tiltY = ty;
});
running = true;
var step = function() {
if(tiltX != undefined) {
x = x * smooth + tiltX * (1 - smooth);
y = y * smooth + tiltY * (1 - smooth);
cb(x,y);
}
if(running) {
window.requestAnimationFrame(step)
}
};
window.requestAnimationFrame(step);
},
stop: function() {
running = false;
provider.stop();
}
}
};
var gyrollaxify = function() {
var elems = $('[data-z]').get();
var zValues = _.map(elems, function(elem) {
elem.style.webkitTransform = 'translate(0px, 0px)';
return parseFloat(elem.attributes['data-z'].value);
});
var backElems = $('[data-back-z]').get();
$(backElems).each(function() {
var z = -parseFloat(this.attributes['data-back-z'].value);
$(this).css({
'background-size': 'calc(100% + ' + (2 * z) + 'px)',
'background-position': '-' + z + 'px -' + z + 'px'
});
});
var backZValues = _.map(backElems, function(elem) {
return -parseFloat(elem.attributes['data-back-z'].value);
});
var provider = SmoothTiltProvider();
provider.start(function(tx, ty) {
for(var i = 0; i < elems.length; i++) {
var elem = elems[i];
var z = zValues[i];
//- elem.style.position = 'relative';
//- elem.style.left = tx * z + 'px';
//- elem.style.top = ty * z + 'px';
elem.style.webkitTransform = 'translate(' + (tx * z) + 'px, ' + (ty * z) + 'px)';
}
for(var i = 0; i < backElems.length; i++) {
var elem = backElems[i];
var z = backZValues[i];
var x = -tx * z - z;
var y = -ty * z - z;
elem.style.backgroundPosition = '' + x + 'px ' + y + 'px';
}
});
};
if(typeof(window) == 'undefined') {
module.exports = {
gyrollaxify: gyrollaxify,
TiltProvider: TiltProvider,
SmoothTiltProvider: SmoothTiltProvider
};
}