Create a gist now

Instantly share code, notes, and snippets.

@abernier /.gitignore
Last active Jan 18, 2017

What would you like to do?
//ax
node_modules/

Hardware-accelerated parallax

Demo: http://bl.ocks.org/abernier/raw/0837661e346360b5385b/

INSTALL

browser-side

<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script src="http://underscorejs.org/underscore.js"></script>
<script src="https://cdn.rawgit.com/abernier/3225993/raw/427b4179e228f79a7f49f8981f3a1d233deb73b7/loop.js"></script>
<script src="parallax.js"></script>

Server-side

npm install https://gist.github.com/abernier/0837661e346360b5385b/archive/847d8c07b85c0532d7a3931f90d522587cd50b85.tar.gz

Usage

$('#my').parallax({amplitude: .5});

or

var el = document.getElementById('my');

var parallax = new Parallax(el, {
  amplitude: .5 // default: 1
});
parallax.loop.start();
<!DOCTYPE html>
<html class="no-js">
<head>
<meta charset="utf-8">
<title></title>
<meta name="viewport" content="width=device-width,minimum-scale=1,maximum-scale=1,initial-scale=1,user-scalable=no">
<style>
p {text-align:center;}
.strong {position:relative;z-index:1; font-size:200%;}
.my {
height:500px; margin:200% 0;
outline:100em solid rgba(255,255,255,.8); box-shadow:inset 0 0 0px 2px red;
background:url(http://lorempixel.com/1400/1900/) center no-repeat; background-size:cover;
overflow:visible!important;
}
.my >div {
position:relative;z-index:-1;
}
.my p {font-size:500%;}
</style>
</head>
<body>
<p class="strong">Scroll down<br>↓↓↓</p>
<p><a href="https://gist.github.com/abernier/0837661e346360b5385b#file-readme-md">README</a>
<div class="my">
<p>Lorem ipsum</p>
</div>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script src="http://underscorejs.org/underscore.js"></script>
<script src="https://rawgit.com/abernier/3225993/raw/7f928620dbe65570950ab551ee06b82e480507bb/loop.js"></script>
<script src="parallax.js"></script>
<script>
$('.my').parallax({amplitude: 1});
</script>
</body>
</html>
{
"name": "parallax",
"version": "0.1.1",
"description": "",
"main": "parallax.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://gist.github.com/0837661e346360b5385b.git"
},
"author": "Antoine BERNIER",
"license": "ISC",
"dependencies": {
"jquery": "^2.1.1",
"loop": "https://gist.github.com/abernier/3225993/archive/427b4179e228f79a7f49f8981f3a1d233deb73b7.tar.gz"
}
}
(function () {
var $ = this.jQuery || require('jquery');
var _ = this._ || require('underscore');
var Loop = this.Loop || require('Loop');
var $html = $('html');
var $window = $(window);
function Parallax(el, options) {
options || (options = {});
this.constructor.insertStyle();
this.$el = $(el);
this.el = this.$el[0];
this.amplitude = options.amplitude || 1;
// Add .parallax class
this.$el.addClass('parallax');
if (this.$el.css('position') === 'static') {
this.$el.css('position', 'relative');
}
// Insert pseudo .img div
this.$img = $('<div class="img"/>').css('background-image', this.$el.css('background-image')).prependTo(this.$el);
this.$el.css('background-image', 'none');
this.loop = new Loop(function () {
var scrolltop = $window.scrollTop();
var percent = this.percent(scrolltop);
//console.log(percent);
this.draw(percent);
}.bind(this));
$(window).on('resize', _.debounce(this.setDims.bind(this), 200));
this.$img.on('webkitTransitionEnd mozTransitionEnd oTransitionEnd msTransitionEnd transitionend', _.debounce(function (e) {
//console.log('transitionend', e.target);
if (!(e.originalEvent.target === this.$img[0] && e.originalEvent.propertyName === 'height')) {
return;
}
e.originalEvent.stopPropagation();
this.setDims();
}.bind(this), 30));
this.setDims();
}
Parallax.prototype.setDims = function () {
//console.log('setDims');
this.offsettop = this.$el.offset().top,
this.WH = $(window).height(),
this.h = this.$el.outerHeight();
this.hh = this.$img.height();
this.minoffsettop = this.offsettop - this.WH;
this.maxoffsettop = this.offsettop + this.h;
this.loop.f();
};
Parallax.prototype.percent = function (scrolltop) {
var percent = ((this.offsettop - scrolltop) + this.h) / (this.WH + this.h);
this.currentPercent = percent;
return percent;
};
Parallax.prototype.draw = function (percent) {
//console.log(percent);
var pmin = .5-this.amplitude/2;
var pmax = .5+this.amplitude/2;
percent = percent * (pmax - pmin) + pmin;
var ty = ~~(-percent*this.hh + (1-percent)*this.h);
var t;
if (Parallax.has3d) {
t = 'translate3d(0,' + ty + 'px,0)';
} else {
t = 'translate(0,' + ty + 'px)';
}
if (percent > 0 && percent < 1) {
this.$img.css('transform', t);
}
return this;
};
// http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support#answer-12621264
function has3d() {
var el = document.createElement('p');
var has3d;
var transforms = {
'webkitTransform':'-webkit-transform',
'OTransform':'-o-transform',
'msTransform':'-ms-transform',
'MozTransform':'-moz-transform',
'transform':'transform'
};
// Add it to the body to get the computed style.
document.body.insertBefore(el, null);
for (var t in transforms) {
if (el.style[t] !== undefined) {
el.style[t] = "translate3d(1px,1px,1px)";
has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
}
}
document.body.removeChild(el);
return (has3d !== undefined && has3d.length > 0 && has3d !== "none");
}
Parallax.has3d = has3d();
Parallax.css = ''
+ '.parallax {overflow:hidden;}'
+ '.parallax >.img {'
+ ' display:block;width:100%;height:200%; background-position:center;background-repeat:no-repeat; -webkit-background-size:cover;-moz-background-size:cover;background-size:cover;'
+ ' position:absolute;left:0;top:0;'
+ ' -webkit-transition:height 1ms;-moz-transition:height 1ms;-o-transition:height 1ms;-ms-transition:height 1ms;transition:height 1ms;'
+ '}'
;
Parallax.insertStyle = function () {
if (this.$style) return; //once
if (!this.$style) {
this.$style = $('<style/>').text(this.css).appendTo(document.head);
}
};
//
// jQuery plugin
//
$.fn.parallax = function (options) {
this.each(function (i, el) {
var $el = $(el);
var parallax = new Parallax(el, options);
parallax.loop.start();
$el.data('parallax', parallax);
});
}
//
// CommonJS
//
this.Parallax = Parallax;
if (typeof module !== "undefined" && module !== null) {
module.exports = this.Parallax;
}
}).call(this);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment