Created
June 21, 2012 20:45
-
-
Save jentanbernardus/2968409 to your computer and use it in GitHub Desktop.
Jarallax is an open-source javascript library which makes adjusting css based on interaction easy. With Jarallax it's easy to create a parallax scrolling website.
This file contains hidden or 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
/*! | |
* jaralax library | |
* version: 0.2.1 public beta | |
* http://jarallax.com/ | |
* | |
* Copyright 2012, Jacko Hoogeveen | |
* Dual licensed under the MIT or GPL Version 3 licenses. | |
* http://jarallax.com/license.html | |
* | |
* Date: 2/29/2012 | |
*/ | |
function hasNumbers(t) | |
{ | |
return /\d/.test(t); | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// jarallax class ////////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
Jarallax = function(controller) { | |
this.jarallaxObject = []; | |
this.animations = []; | |
this.defaultValues = []; | |
this.progress = 0.0; | |
this.controllers = []; | |
this.maxProgress = 1; | |
if (controller === undefined) { | |
this.controllers.push(new ControllerScroll()); | |
} else { | |
if (controller.length) { | |
this.controllers = controller; | |
} else if (typeof (controller) === 'object') { | |
this.controllers.push(controller); | |
} else { | |
throw new Error('wrong controller data type: "' + typeof (controller) + '". Expected "object" or "array"'); | |
} | |
} | |
for (var i = 0; i < this.controllers.length; i++){ | |
this.controllers[i].activate(this); | |
} | |
}; | |
//////////////////////////////////////////////////////////////////////////////// | |
// Jarallax methods //////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
Jarallax.prototype.setProgress = function (progress) { | |
if(progress > 1){ | |
progress = 1; | |
}else if(progress < 0){ | |
progress = 0; | |
}else{ | |
this.progress = progress; | |
} | |
for(j = 0; j < this.defaultValues.length; j++){ | |
this.defaultValues[j].activate(progress); | |
} | |
for(k = 0; k < this.animations.length; k++){ | |
this.animations[k].activate(progress); | |
} | |
for(l = 0; l < this.controllers.length; l++){ | |
this.controllers[l].update(progress); | |
} | |
}; | |
Jarallax.prototype.setDefault = function (selector, values) { | |
if(!selector){ | |
throw new Error('no selector defined.'); | |
} | |
if(Jarallax.isValues(values)) | |
{ | |
var newDefault = new JarallaxDefault(selector, values); | |
newDefault.activate(); | |
this.defaultValues.push(newDefault); | |
} | |
}; | |
Jarallax.prototype.addStatic = function (selector, values) { | |
if(!selector){ | |
throw new Error('no selector defined.'); | |
} | |
if(Jarallax.isValues(values)) | |
{ | |
var newDefault = new JarallaxStatic(selector, values[0], values[1]); | |
this.defaultValues.push(newDefault); | |
} | |
}; | |
Jarallax.prototype.addAnimation = function (selector, values) { | |
if(!selector) { | |
throw new Error('no selector defined.'); | |
} | |
if(Jarallax.isValues(values)) { | |
for(var i = 0; i < values.length - 1; i++){ | |
if(values[i] && values[i + 1]) | |
{ | |
if(values[i]['progress'] && values[i + 1]['progress']) { | |
if(values[i + 1]['progress'].indexOf('%') == -1) { | |
if(this.maxProgress < values[i + 1]['progress']){ | |
this.maxProgress = values[i + 1]['progress']; | |
} | |
} | |
this.animations.push(new JarallaxAnimation(selector, values[i], values[i + 1], this)); | |
} | |
else | |
{ | |
throw new Error('no animation boundry found.'); | |
} | |
} | |
else | |
{ | |
throw new Error('bad animation data.'); | |
} | |
} | |
} | |
}; | |
JarallaxDefault = function (selector, values) { | |
this.selector = selector; | |
this.values = values; | |
}; | |
JarallaxDefault.prototype.activate = function (position) { | |
for(i in this.values){ | |
$(this.selector).css(i,this.values[i]); | |
} | |
}; | |
JarallaxStatic = function (selector, startValues, endValues) { | |
this.selector = selector; | |
this.values = values; | |
}; | |
JarallaxStatic.prototype.activate = function(position) { | |
var start; | |
var end; | |
if(this.startValues['progress'].indexOf('%') >= 0) { | |
start = parseInt(this.startValues['progress'],10) / 100; | |
}else if(hasNumbers(this.startValues['progress'])){ | |
start = this.maxProgress / parseInt(this.startValues['progress'],10); | |
} | |
if(this.endValues['progress'].indexOf('%') >= 0) | |
{ | |
end = parseInt(this.endValues['progress'],10) / 100; | |
}else if(hasNumbers(this.endValues['progress'])){ | |
end = this.maxProgress / parseInt(this.endValues['progress'],10); | |
} | |
if(progress > start && progress < end ) { | |
for(i in this.startValues){ | |
if(i != 'progress') | |
{ | |
$(this.selector).css(i, this.startValues[i]); | |
} | |
} | |
} | |
}; | |
//////////////////////////////////////////////////////////////////////////////// | |
// Jarallax static methods ///////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
Jarallax.isValues = function(object) { | |
if(!object) { | |
throw new Error('no values set.'); | |
} | |
if(typeof object != 'object') { | |
throw new Error('wrong data type values. expected: "object", got: "' + typeof object + '"'); | |
} | |
if(object.size === 0) { | |
throw new Error('Got an empty values object'); | |
} | |
return true; | |
}; | |
Jarallax.getUnits = function (string) { | |
return string.replace(/\d+/g, ''); | |
}; | |
Jarallax.EASING = { | |
'linear':function (currentTime, beginningValue, changeInValue, duration, power) { | |
return currentTime / duration * changeInValue + beginningValue; | |
}, | |
'easeOut':function (currentTime, beginningValue, changeInValue, duration, power) { | |
if(power == undefined){ | |
power = 2; | |
} | |
return ((Math.pow((duration - currentTime) / duration, power) * -1) + 1) * changeInValue + beginningValue; | |
}, | |
'easeIn':function (currentTime, beginningValue, changeInValue, duration, power) { | |
if(power == undefined){ | |
power = 2; | |
} | |
return Math.pow(currentTime / duration, power) * changeInValue + beginningValue; | |
}, | |
'easeInOut':function (currentTime, beginningValue, changeInValue, duration, power) { | |
if(power == undefined){ | |
power = 2; | |
} | |
changeInValue /= 2; | |
currentTime *= 2; | |
if(currentTime < duration){ | |
return Math.pow(currentTime / duration, power) * changeInValue + beginningValue; | |
}else{ | |
currentTime = currentTime - duration; | |
return ((Math.pow((duration - currentTime) / duration, power) * -1) + 1) * changeInValue + beginningValue + changeInValue; | |
} | |
return Math.pow(currentTime / duration, power) * changeInValue + beginningValue; | |
} | |
}; | |
Jarallax.EASING['none'] = Jarallax.EASING['linear']; | |
//////////////////////////////////////////////////////////////////////////////// | |
// Jarallax animation class //////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
JarallaxAnimation = function (selector, startValues, endValues, jarallax) { | |
this.progress = 0; | |
this.selector = selector; | |
this.startValues = startValues; | |
this.endValues = endValues; | |
this.jarallax = jarallax; | |
}; | |
JarallaxAnimation.prototype.activate = function (progress) { | |
if(this.progress != progress){ | |
var start; | |
var end; | |
var style; | |
if (this.startValues['style'] == undefined){ | |
style = {easing:'linear'}; | |
}else{ | |
style = this.startValues['style']; | |
} | |
if(this.startValues['progress'].indexOf('%') >= 0) { | |
start = parseInt(this.startValues['progress'],10) / 100; | |
}else if(hasNumbers(this.startValues['progress'])){ | |
start = parseInt(this.startValues['progress'],10) / this.jarallax.maxProgress; | |
} | |
if(this.endValues['progress'].indexOf('%') >= 0) | |
{ | |
end = parseInt(this.endValues['progress'],10) / 100; | |
}else if(hasNumbers(this.endValues['progress'])){ | |
end = parseInt(this.endValues['progress'],10) / this.jarallax.maxProgress; | |
} | |
if(this.startValues['event']){ | |
this.dispatchEvent(this.progress, progress, start, end); | |
} | |
if(progress >= start && progress <= end ){ | |
for(i in this.startValues){ | |
if(i != 'progress' && i != 'style' && i != 'event') | |
{ | |
if(undefined!=this.endValues[i] && i != 'display'){ | |
var units = Jarallax.getUnits(this.startValues[i]+''); | |
units = units.replace('-',''); | |
var startValue = parseFloat(this.startValues[i]); | |
var endValue = parseFloat(this.endValues[i]); | |
var duration = end - start; | |
var currentTime = (progress-start); | |
var changeInValue = endValue - startValue ; | |
var result = Jarallax.EASING[style['easing']](currentTime, startValue , changeInValue, duration, style['easing']['power']); | |
result+= units; | |
$(this.selector).css(i,result); | |
} | |
else | |
{ | |
$(this.selector).css(i,this.startValues[i]); | |
} | |
} | |
} | |
} | |
this.progress = progress; | |
} | |
}; | |
JarallaxAnimation.prototype.dispatchEvent = function(progress_old, progress_new, start, end){ | |
var events = this.startValues['event']; | |
var event_data = {}; | |
event_data.animation = this; | |
event_data.selector = this.selector; | |
if(progress_new >= start && progress_new <= end ) { | |
if(events.start && progress_old < start) { | |
event_data.type = 'start'; | |
events.start(event_data); | |
} | |
if(events.animating){ | |
event_data.type = 'animating'; | |
events.animating(event_data); | |
} | |
if(events.forward && progress_old < progress_new) { | |
event_data.type = 'forward'; | |
events.forward(event_data); | |
} | |
if(events.reverse && progress_old > progress_new) { | |
event_data.type = 'reverse'; | |
events.reverse(event_data); | |
} | |
} else { | |
if(events.complete && progress_old < end && progress_new > end) { | |
event_data.type = 'complete'; | |
events.complete(event_data); | |
} | |
if(events.rewinded && progress_old > start && progress_new < start) { | |
event_data.type = 'rewinded'; | |
events.rewinded(event_data); | |
} | |
} | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Scroll controller /////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
ControllerScroll = function(){ | |
this.height = parseInt(jQuery("body").css("height"),10); | |
this.target = $(window); | |
this.scrollSpace = this.height - this.target.height(); | |
}; | |
ControllerScroll.prototype.activate = function(jarallax){ | |
this.jarallax = jarallax; | |
this.target.bind('scroll', {me: this} , this.onScroll); | |
}; | |
ControllerScroll.prototype.deactivate = function(jarallax){ | |
//TODO | |
}; | |
ControllerScroll.prototype.onScroll = function(event){ | |
var controller = event.data.me; | |
var y = controller.target.scrollTop(); | |
var progress = y/controller.scrollSpace; | |
controller.jarallax.setProgress(progress); | |
}; | |
ControllerScroll.prototype.update = function(progress){ | |
//empty | |
}; | |
//////////////////////////////////////////////////////////////////////////////// | |
// Time controller ///////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
ControllerTime = function(speed, interval){ | |
this.interval = interval; | |
this.speed = speed; | |
this.forward = true; | |
}; | |
ControllerTime.prototype.onInterval = function(){ | |
this.jarallax.setProgress(this.progress); | |
$('body').scrollTop(parseInt(jQuery("body").css("height"), 10) * this.progress); | |
if(this.progress >= 1){ | |
this.progress = 1; | |
this.forward = false; | |
}else if(this.progress <= 0){ | |
this.progress = 0; | |
this.forward = true; | |
} | |
if(this.forward){ | |
this.progress+= this.speed; | |
}else{ | |
this.progress-= this.speed; | |
} | |
}; | |
ControllerTime.prototype.activate = function(jarallax){ | |
this.jarallax = jarallax; | |
this.progress = 0; | |
this.interval = $.interval(this.onInterval.bind(this), this.interval); | |
}; | |
ControllerTime.prototype.deactivate = function(jarallax){ | |
//TODO | |
}; | |
ControllerTime.prototype.update = function(progress){ | |
//empty | |
}; | |
//////////////////////////////////////////////////////////////////////////////// | |
// onDrag controller ///////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
ControllerDrag = function(selector, start, end){ | |
this.object = $(selector); | |
this.start = start; | |
this.end = end; | |
this.container = ""; | |
this.width; | |
this.startX = 0; | |
this.startY = 0; | |
}; | |
ControllerDrag.prototype.activate = function(jarallax){ | |
this.jarallax = jarallax; | |
this.container = "#scrollbar"; | |
this.object.draggable({containment:this.container, axis: 'x'}); | |
this.object.bind("drag", {me: this}, this.onDrag); | |
this.container = $(this.container); | |
this.width = $(this.container).innerWidth() - this.object.outerWidth(); | |
}; | |
ControllerDrag.prototype.onDrag = function(event){ | |
var x = parseInt($(this).css('left'), 10); | |
var position = (x / event.data.me.width); | |
event.data.me.jarallax.setProgress(position); | |
}; | |
ControllerDrag.prototype.deactivate = function(jarallax){ | |
//TODO | |
}; | |
ControllerDrag.prototype.update = function(progress){ | |
this.object.css('left', progress * this.width); | |
}; | |
//////////////////////////////////////////////////////////////////////////////// | |
// Keyboard controller ///////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
ControllerKeyboard = function(keys, preventDefault, repetitiveInput){ | |
this.repetitiveInput = repetitiveInput; | |
this.preventDefault = preventDefault || false; | |
this.keys = keys || {38:-0.01, 40:0.01}; | |
this.keysState = new Object(); | |
}; | |
ControllerKeyboard.prototype.activate = function(jarallax){ | |
this.jarallax = jarallax; | |
$(document.documentElement).keydown({me: this}, this.keyDown); | |
$(document.documentElement).keyup({me: this}, this.keyUp); | |
for(key in this.keys){ | |
this.keysState[key] = false; | |
} | |
}; | |
ControllerKeyboard.prototype.deactivate = function(jarallax){ | |
//TODO | |
}; | |
ControllerKeyboard.prototype.keyDown = function(event){ | |
var controller = event.data.me; | |
for(key in controller.keys){ | |
if(key == event.keyCode){ | |
if(controller.keysState[key] !== true || controller.repetitiveInput){ | |
controller.jarallax.setProgress(controller.jarallax.progress + controller.keys[key]); | |
} | |
controller.keysState[key] = true; | |
if(controller.preventDefault){ | |
event.preventDefault(); | |
} | |
} | |
} | |
}; | |
ControllerKeyboard.prototype.keyUp = function(event){ | |
var controller = event.data.me; | |
for(key in controller.keys){ | |
if(key == event.keyCode){ | |
controller.keysState[key] = false; | |
} | |
} | |
}; | |
ControllerKeyboard.prototype.update = function(progress){ | |
//empty | |
}; | |
//////////////////////////////////////////////////////////////////////////////// | |
// Mousewheel controller /////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
ControllerMousewheel = function(sensitivity, preventDefault){ | |
this.sensitivity = -sensitivity; | |
this.preventDefault = preventDefault || false; | |
}; | |
ControllerMousewheel.prototype.activate = function(jarallax){ | |
this.jarallax = jarallax; | |
$('body').bind('mousewheel', {me: this} , this.onScroll); | |
}; | |
ControllerMousewheel.prototype.deactivate = function(jarallax){ | |
this.jarallax = jarallax; | |
}; | |
ControllerMousewheel.prototype.onScroll = function(event, delta){ | |
controller = event.data.me; | |
controller.jarallax.setProgress(controller.jarallax.progress + controller.sensitivity * delta); | |
if(controller.preventDefault){ | |
event.preventDefault(); | |
} | |
}; | |
ControllerMousewheel.prototype.update = function(progress){ | |
//empty | |
}; | |
//////////////////////////////////////////////////////////////////////////////// | |
// IPAD controller ///////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
ControllerIpadScroll = function(){ | |
this.x = 0; | |
this.previousX = -1; | |
this.top = 700; | |
this.moveRight = false; | |
}; | |
ControllerIpadScroll.prototype.activate = function(jarallax, values){ | |
this.jarallax = jarallax; | |
this.values = values; | |
$('body').bind('touchmove', {me: this}, this.onScroll); | |
//TODO: | |
//horizontal scrolling | |
//flip_direction | |
}; | |
ControllerIpadScroll.prototype.onScroll = function(event){ | |
event.preventDefault(); | |
var me = event.data.me; | |
var targetEvent = event.originalEvent.touches.item(0); | |
if(me.previousX == -1) { | |
me.previousX = targetEvent.clientX; | |
} | |
else | |
{ | |
if(targetEvent.clientX - me.previousX < 100 && targetEvent.clientX - me.previousX > -100) | |
{ | |
if(me.moveRight) | |
{ | |
me.x -= (targetEvent.clientX - me.previousX); | |
} | |
else | |
{ | |
me.x += (targetEvent.clientX - me.previousX); | |
} | |
me.x = me.x < 1000 ? me.x : 1000; | |
me.x = me.x > 0 ? me.x : 0; | |
} | |
me.previousX = targetEvent.clientX; | |
me.jarallax.setProgress(me.x/me.top); | |
} | |
}; | |
ControllerIpadScroll.prototype.deactivate = function(jarallax){ | |
//TODO | |
}; | |
ControllerIpadScroll.prototype.update = function(progress){ | |
//empty | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment