Skip to content

Instantly share code, notes, and snippets.

@bpander
Created September 24, 2012 17:16
Show Gist options
  • Save bpander/3777101 to your computer and use it in GitHub Desktop.
Save bpander/3777101 to your computer and use it in GitHub Desktop.
parallax framework for creating Tweens and Switches based on the user's scroll position
/**
* parallax.js
* @author Brad Anderson
* @description Tween elements based on the users scroll position or flip a switch when the user gets to a certain point in the page
* @requires Nothing
* @example
* var tween = new parallax.Tween(
document.getElementById('pizza'),
'left',
'0px',
'300px',
20,
220
);
parallax.init();
*/
var parallax = (function() {
var parallax = {};
var _tweens = [];
var _switches = [];
var _scrollTop = 0;
var _lastScrollTop = 0;
var _getSupportedProperty = function(property) {
var div = document.createElement('div');
var supportedProperty = null;
if (property in div.style) {
supportedProperty = property;
} else {
var capitalizedProperty = property.charAt(0).toUpperCase() + property.slice(1);
var prefixes = ['Moz', 'Webkit', 'O', 'ms'];
var l = prefixes.length;
for (var i = 0; i < l; i++) {
var vendorProperty = prefixes[i] + capitalizedProperty;
if (vendorProperty in div.style) {
supportedProperty = vendorProperty;
break;
}
}
}
div = null;
return supportedProperty;
};
var _transitionProperty = _getSupportedProperty('transition');
var _defaultEasingFunction = function(p) {
return 0.5 + 0.5 * Math.sin(Math.PI * ( p - 0.5 ));
};
/**
* Start listening for the scroll event, also figure out where all the elements need to be
*/
parallax.init = function() {
_onScroll();
document.addEventListener('scroll', _onScroll, false);
};
/**
* Stop listening for the scroll event, also empty the private tweens array
*/
parallax.exit = function() {
document.removeEventListener('scroll', _onScroll);
_tweens = [];
};
/**
* Tween an element based on how many pixels the user has scrolled
* @class parallax.Tween
* @param {DOM Element} element The element to animate
* @param {String} property The CSS property to animate
* @param {String} start The initial value when we start animating (with units e.g. '0px')
* @param {String} end The final value when we stop animating (with units e.g. '200px')
* @param {Number} delay How many pixels will the user have scrolled when the animation starts
* @param {Number} animationEnd How many pixels will the user have scrolled when the animation finishes
* @param {Function} easingFunction Optional. A function taking the percentComplete of pixels scrolled and outputting the percentComplete of the animation
*/
parallax.Tween = function ParallaxTween(
element,
property,
start,
end,
delay,
animationEnd,
easingFunction
) {
this.element = element;
this.property = property;
this.start = parseFloat(start);
this.end = parseFloat(end);
this.delay = delay;
this.animationEnd = animationEnd;
this.easingFunction = easingFunction || _defaultEasingFunction;
this.isAnimating = false;
this.range = this.animationEnd - this.delay;
this.change = this.end - this.start;
this.units = start.split(this.start)[1];
//this.element.style[_transitionProperty] = property + ' 0.1s';
_tweens.push(this);
};
/**
* Flip a switch when a user scrolls x pixels
* @class parallax.Switch
* @param {DOM Element} element The element to change
* @param {String} property The CSS property to change
* @param {String} start The value of the CSS property *before* we scroll x pixels
* @param {String} end The value of the CSS property *after* we scroll x pixels
* @param {Number} delay How many pixels will the user have scrolled when we make the switch
*/
parallax.Switch = function ParallaxSwitch(
element,
property,
start,
end,
delay
) {
this.element = element;
this.property = property;
this.start = start;
this.end = end;
this.delay = delay;
_switches.push(this);
};
var _onScroll = function(e) {
_scrollTop = window.pageYOffset || document.scrollTop || 0;
var l = _tweens.length;
for (var i = 0; i < l; i++) {
var tween = _tweens[i];
if (_scrollTop > tween.animationEnd || _scrollTop < tween.delay) {
if (tween.isAnimating) {
if (_lastScrollTop > _scrollTop) {
tween.element.style[tween.property] = tween.start + tween.units;
} else {
tween.element.style[tween.property] = tween.end + tween.units;
}
tween.isAnimating = false;
}
continue;
}
tween.isAnimating = true;
var percentComplete = (_scrollTop - tween.delay) / tween.range;
var position = tween.start + tween.change * tween.easingFunction(percentComplete);
tween.element.style[tween.property] = position + tween.units;
}
l = _switches.length;
for (var i = 0; i < l; i++) {
var _switch = _switches[i];
if (_lastScrollTop < _switch.delay && _scrollTop >= _switch.delay) {
_switch.element.style[_switch.property] = _switch.end;
} else if (_lastScrollTop > _switch.delay && _scrollTop < _switch.delay) {
_switch.element.style[_switch.property] = _switch.start;
}
}
_lastScrollTop = _scrollTop;
};
return parallax;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment