Skip to content

Instantly share code, notes, and snippets.

@razwan
Last active August 4, 2016 06:28
Show Gist options
  • Save razwan/4a6db4f564255f1d92133088ef264192 to your computer and use it in GitHub Desktop.
Save razwan/4a6db4f564255f1d92133088ef264192 to your computer and use it in GitHub Desktop.
jQuery Parallax Plugin
// the semi-colon before the function invocation is a safety
// net against concatenated scripts and/or other plugins
// that are not closed properly.
;(function ($, window, document, undefined) {
var windowHeight = $(window).height(),
lastKnownScrollY;
$(window).on('resize', function(e) {
windowHeight = $(window).height();
});
$(window).on('load scroll', function(e) {
lastKnownScrollY = $(e.target).scrollTop();
});
// constructor
function PluginName(element, options) {
this.element = element;
// jQuery has an extend method that merges the
// contents of two or more objects, storing the
// result in the first object. The first object
// is generally empty because we don't want to alter
// the default options for future instances of the plugin
this.options = $.extend({}, $.fn.pluginName.defaults, options);
// save this into another variable ie. self
// so we can acces it scoped functions like event handlers
var self = this,
$el = $(this.element),
myAmount;
// override plugin options at element level via data-attirbutes
myAmount = $el.data('parallaxamount');
this.isContainer = $el.is(self.options.containerSelector);
this.$parent = $el.parent().closest(self.options.containerSelector);
this.options.amount = myAmount != undefined ? parseFloat(myAmount) : this.options.amount;
// if (this.options.amount == 0) return;
$(window).on('load resize', function(e) {
self._reloadElement();
self._updatePosition();
});
$(window).on('load scroll', function(e) {
// this should apply only to background elements
// if (self._isInViewport()) {
self._updatePosition();
// }
});
}
$.extend(PluginName.prototype, {
constructor: PluginName,
_reloadElement: function() {
var self = this,
$el = $(this.element).removeAttr('style');
if ( self.$parent ) {
self.$parent.css('position', 'static');
// } else {
// $el.css('position', '');
}
self.width = $el.width();
self.height = $el.height();
self.offset = $el.offset();
if ( self.isContainer ) {
self.width += 2 * self.options.gutter;
self.height += 2 * self.options.gutter;
self.offset.left -= self.options.gutter;
self.offset.top -= self.options.gutter;
}
if ( self.$parent ) {
self.$parent.css({
position: 'fixed',
overflow: 'hidden',
zIndex: -1
});
}
$el.css({
position: 'fixed',
top: self.offset.top,
left: self.offset.left,
width: self.width,
height: self.height,
marginTop: 0,
marginLeft: 0
});
},
_isInViewport: function() {
return lastKnownScrollY > this.offset.top - windowHeight && lastKnownScrollY < this.offset.top + this.height
},
_updatePosition: function() {
var self = this,
progress = (lastKnownScrollY - this.offset.top + windowHeight) / (windowHeight + this.height),
move = (windowHeight + this.height) * (progress - 0.5);
// if element is in viewport
if (lastKnownScrollY > this.offset.top - windowHeight + move && lastKnownScrollY < this.offset.top + this.height + move) {
if ( !self.$parent.length && !self.isVisible ) {
$(self.element).show();
self.isVisible = true;
}
requestAnimationFrame(function() {
if (self.isContainer) {
$(self.element).css('transform', 'translate3d(0,' + (-lastKnownScrollY) + 'px,0)');
$(self.element).find('[data-parallaxtarget]').css('top', lastKnownScrollY * self.options.amount);
} else {
$(self.element).css('transform', 'translate3d(0,' + (move * self.options.amount - lastKnownScrollY) + 'px,0)');
}
});
} else {
if ( !self.$parent.length && self.isVisible ) {
$(self.element).hide();
self.isVisible = false;
}
}
}
});
$.fn.pluginName = function ( options ) {
return this.each(function () {
if ( ! $.data(this, "plugin_" + PluginName) ) {
$.data(this, "plugin_" + PluginName, new PluginName( this, options ));
}
});
}
$.fn.pluginName.defaults = {
amount: 0.5,
gutter: 10,
containerSelector: '[data-parallaxcontainer]'
};
})( jQuery, window, document );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment