Skip to content

Instantly share code, notes, and snippets.

@hapticdata
Last active December 10, 2015 13:08
Show Gist options
  • Save hapticdata/4439271 to your computer and use it in GitHub Desktop.
Save hapticdata/4439271 to your computer and use it in GitHub Desktop.
starting point for binding an event (such as scroll) with various properties
/*
example:
new ParallaxSprite({
el: $('#element'),
watch: {
fn: function(){ return $(window).scrollTop(); },
from: 0,
to: 1000
},
tween: {
'top': {
from: 0,
to: -500
},
'box-shadow': {
from: 0,
to: 4
}
}
});
or use html:
<img src="img.jpg" data-plax-watch-from="0" data-plax-watch-to="1000" data-plax-tween="top" data-plax-tween-from="1000" data-plax-tween-to="-100" >
$('[data-plax-watch-to]').each(function(){ parallaxSprite({ el: this }); });
*/
define(function( require, exports, module ){
var $ = require('jquery'),
_ = require('underscore'),
Backbone = require('backbone'),
Rect = require('toxi/geom/Rect'),
ScaleMap = require('toxi/math/ScaleMap');
var ParallaxSprite = Backbone.View.extend({
tagName: 'div',
className: 'parallax-sprite',
initialize: function(){
_.bindAll(this,'applyTween','bindScroll','__renderFirst','render');
},
applyTween: function(){
//update the css, via the scalemap for every property
var css = {};
for( var prop in this.tween ){
css[prop] = this.tween[prop].current;
}
this.$el.css( css );
},
bindScroll: function(){
if( !this.rendered ){
this.render();
}
$(window).scroll(this.render);
return this;
},
eachTween: function( fn ){
for( var prop in this.tween ){
fn( this.tween[prop], prop );
}
return this;
},
isAtBeginning: function(){
for( var prop in this.tween ){
if( this.tween[prop].current !== this.tween[prop].from ){
return false;
}
}
return true;
},
isAtEnd: function(){
for( var prop in this.tween ){
if( this.tween[prop].current !== this.tween[prop].to ){
return false;
}
}
return true;
},
__renderFirst: function(){
var watchProp;
//this.rect = new Rect({ x: 0, y: this.offsetY, width: this.$el.width(), height: this.$el.height() });
if( this.options.applyTween ){
this.applyTween = this.options.applyTween;
}
if( this.options.watch ){
this.watch = {};
if( this.options.watch.fn ){
this.watch.fn = this.options.watch.fn;
} else {
//there should be a watch: {property: "" }
//if there isnt, watch scrollTop
watchProp = this.options.watch.property || 'scrollTop';
this.watch.fn = function(){ return $(window)[watchProp](); };
}
this.watch.from = this.options.watch.from;
this.watch.to = this.options.watch.to;
}
if( this.options.tween ){
this.tween = this.options.tween;
this.maps = {};
//create a scalemap for every tweening property
for( var prop in this.tween ){
this.maps[prop] = new ScaleMap({
input: {
min: this.watch.from,
max: this.watch.to
},
output: {
min: this.tween[prop].from,
max: this.tween[prop].to
}
});
this.tween[prop].current = this.maps[prop].getClippedValueFor( this.watch.fn() );
}
}
this.rendered = true;
this.__atBeginning = this.isAtBeginning();
this.__atEnd = this.isAtEnd();
},
render: function(){
if( !this.rendered ){
this.__renderFirst();
}
//get the current value for our watched property
var current = this.watch.fn();
//update the css, via the scalemap for every property
var css = {};
for( var prop in this.tween ){
this.tween[prop].current = this.maps[prop].getClippedValueFor( current );
}
if( this.__atBeginning && !this.isAtBeginning() ){
this.trigger('begin');
this.__atBeginning = false;
} else if( !this.__atEnd && this.isAtEnd() ){
this.trigger('end');
this.__atEnd = true;
}
this.applyTween();
return this;
},
remove: function(){
this.unbindScroll();
Backbone.View.prototype.remove.call(this);
},
unbindScroll: function(){
$(window).unbind('scroll', this.render );
return this;
}
});
exports = module.exports = function( opts ){
opts = opts || {};
var tweenProp;
if( opts.el ){
var $el = $(opts.el);
if( !opts.watch ){
opts.watch = {};
opts.watch.property = $el.attr('data-plax-watch');
if( opts.watch.property === undefined ){
opts.watch.property = "scrollTop";
}
opts.watch.from = Number( $el.attr('data-plax-watch-from') );
if( isNaN( opts.watch.from ) ){
opts.watch.from = 0;
}
opts.watch.to = Number( $el.attr('data-plax-watch-to') );
if( isNaN( opts.watch.to ) ){
throw Error("Invalid ParallaxSprite requested, no watch param or data-plax-watch attributes");
}
}
if( !opts.tween ){
opts.tween = {};
tweenProp = $el.attr('data-plax-tween');
if( tweenProp === undefined ){
tweenProp = 'top';
}
opts.tween[ tweenProp ] = {
from: Number( $el.attr('data-plax-tween-from') ),
to: Number( $el.attr('data-plax-tween-to') )
};
if( isNaN(opts.tween[tweenProp].from) ){
opts.tween[tweenProp].from = 0;
}
if( isNaN(opts.tween[tweenProp].to) ){
throw Error("Invalid ParallaxSprite, incorrect tween params or no data-plax-tween attributes");
}
}
}
return new ParallaxSprite( opts );
};
exports.ParallaxSprite = ParallaxSprite;
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment