Skip to content

Instantly share code, notes, and snippets.

@botmad
Created January 10, 2019 09:49
Show Gist options
  • Save botmad/7cf32a4c32f9f4e1e043be6d58e18f44 to your computer and use it in GitHub Desktop.
Save botmad/7cf32a4c32f9f4e1e043be6d58e18f44 to your computer and use it in GitHub Desktop.
Parallax Image
<div class="container" ng-app="parallaxApp" ng-controller="mainCtrl">
<div class="parallaximage-container" parallax>
<img class="layer layer0" src="http://jaromvogel.com/images/design/jumping_rabbit/page2layer0.png"/>
<img class="layer layer1" src="http://jaromvogel.com/images/design/jumping_rabbit/page2layer1.png"/>
<img class="layer layer2" src="http://jaromvogel.com/images/design/jumping_rabbit/page2layer2.png"/>
<img class="layer layer3" src="http://jaromvogel.com/images/design/jumping_rabbit/page2layer3.png"/>
<img class="layer layer4" src="http://jaromvogel.com/images/design/jumping_rabbit/page2layer4.png"/>
</div>
<div class="instructions">
Move mouse over image, or touch and drag
</div>
</div>

Parallax Image

Example of adding a parallax effect to image layers. Works with cursor hover on desktop, and touch+drag on mobile.

A Pen by Jarom Vogel on CodePen.

License.

var app = angular.module("parallaxApp", []);
app.controller('mainCtrl', ['$scope',
function($scope) {
}
]);
app.directive('parallax', function() {
return {
restrict: 'A',
link: function(scope, element, attr) {
// Initialize layers
var all = element.find('.layer0, .layer1, .layer2, .layer3');
var layer0 = element.find('.layer0');
var layer1 = element.find('.layer1');
var layer2 = element.find('.layer2');
var layer3 = element.find('.layer3');
layers = document.querySelectorAll('.layer');
// Move images based on hover
var mouseentered = false;
var entrypoint = null;
var currentpoint = null;
element.bind('mouseenter', function(event) {
mouseentered = true;
entrypoint = {
x: event.offsetX,
y: event.offsetY
};
});
element.bind('mousemove', function(event) {
if (mouseentered === true) {
currentpoint = {
x: event.offsetX,
y: event.offsetY
};
var deltax = currentpoint.x - entrypoint.x;
var deltay = currentpoint.y - entrypoint.y;
layer3.css({
transform: 'translate3d(' + deltax / 30 + 'px,' + deltay / 30 + 'px,0)',
webkitTransform: 'translate3d(' + deltax / 30 + 'px,' + deltay / 30 + 'px,0)',
})
layer2.css({
transform: 'translate3d(' + deltax / 22 + 'px,' + deltay / 22 + 'px,0)',
webkitTransform: 'translate3d(' + deltax / 22 + 'px,' + deltay / 22 + 'px,0)',
})
layer1.css({
transform: 'translate3d(' + deltax / 20 + 'px,' + deltay / 20 + 'px,0)',
webkitTransform: 'translate3d(' + deltax / 20 + 'px,' + deltay / 20 + 'px,0)',
})
layer0.css({
transform: 'translate3d(' + deltax / 10 + 'px,' + deltay / 10 + 'px,0)',
webkitTransform: 'translate3d(' + deltax / 10 + 'px,' + deltay / 10 + 'px,0)',
})
}
});
element.bind('mouseout', function(event) {
mouseentered = false;
dynamics.animate(layers, {
translateX: 0,
translateY: 0,
}, {
type: dynamics.spring,
friction: 200,
duration: 250,
});
});
// Move images based on touch and drag
var touchstart = false;
var startpoint = null;
element.bind('touchstart', function(event) {
touchstart = true;
startpoint = {
x: event.originalEvent.touches[0].pageX,
y: event.originalEvent.touches[0].pageY
}
});
element.bind('touchmove', function(event) {
if (touchstart === true) {
event.preventDefault();
var deltax = event.originalEvent.touches[0].pageX - startpoint.x;
var deltay = event.originalEvent.touches[0].pageY - startpoint.y;
layer3.css({
transform: 'translate3d(' + -deltax / 40 + 'px,' + -deltay / 40 + 'px,0)',
webkitTransform: 'translate3d(' + -deltax / 40 + 'px,' + -deltay / 40 + 'px,0)',
});
layer2.css({
transform: 'translate3d(' + -deltax / 30 + 'px,' + -deltay / 30 + 'px,0)',
webkitTransform: 'translate3d(' + -deltax / 30 + 'px,' + -deltay / 30 + 'px,0)',
});
layer1.css({
transform: 'translate3d(' + -deltax / 25 + 'px,' + -deltay / 25 + 'px,0)',
webkitTransform: 'translate3d(' + -deltax / 25 + 'px,' + -deltay / 25 + 'px,0)',
});
layer0.css({
transform: 'translate3d(' + -deltax / 15 + 'px,' + -deltay / 15 + 'px,0)',
webkitTransform: 'translate3d(' + -deltax / 15 + 'px,' + -deltay / 15 + 'px,0)',
});
}
});
element.bind('touchend', function(event) {
touchstart = false;
dynamics.animate(layers, {
translateX: 0,
translateY: 0,
}, {
type: dynamics.spring,
friction: 100,
duration: 350,
});
});
}
}
})
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.14/angular.min.js"></script>
<script src="https://jaromvogel.com/js/lib/dynamics.min.js"></script>
* {
box-sizing: border-box;
}
body {
font-family: sans-serif;
margin: 0;
}
.container {
position: absolute;
height: 100%;
width: 100%;
}
.parallaximage-container {
width: 300px;
height: 300px;
top: 50%;
transform: translateY(-50%);
position: relative;
margin: 0 auto;
overflow: hidden;
img {
position: absolute;
width: 100%;
}
}
.instructions {
text-align: center;
position: absolute;
bottom: 0;
width: 100%;
font-size: 12px;
line-height: 60px;
height: 60px;
background: white;
}
@media (max-width: 767px) {
.parallaximage-container {
width: 320px;
height: 320px;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment