Created
July 1, 2017 17:39
-
-
Save celsowhite/1c8d0696a75aad45ca92bfb499f24ec2 to your computer and use it in GitHub Desktop.
Parallax function that can be applied to any element on a page. Control the elements speed and rotation.
This file contains 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
/*================================= | |
General Parallax Elements | |
=================================*/ | |
const parallaxItems = document.querySelectorAll('.parallax_item'); | |
const windowHeight = window.innerHeight; | |
// Check each item to see if it is in view on page load so we can set a base position | |
Array.from(parallaxItems).forEach(item => { | |
if(item.getBoundingClientRect().bottom < window.innerHeight) { | |
item.base = (-item.getBoundingClientRect().top + window.innerHeight) / (item.clientHeight + window.innerHeight); | |
} | |
else { | |
item.base = 0; | |
} | |
}); | |
// On scroll check the position of an item and if in view then parallax it based on the speed and rotate settings | |
function checkParallaxItems() { | |
Array.from(parallaxItems).forEach(item => { | |
// Window Measurements | |
let windowPosition = window.scrollY; | |
let windowBottomPosition = window.scrollY + windowHeight; | |
// Item distances from way top of page | |
let itemTop = item.getBoundingClientRect().top + window.scrollY; | |
let itemBottom = item.getBoundingClientRect().bottom + window.scrollY; | |
// Conditionals | |
// Bottom of item is greater than the scroll position | |
// Meaning we havn't scrolled past the item yet | |
let itemBelowTop = itemBottom >= window.scrollY; | |
// Top of item is less than the bottom scroll position of our window | |
// Meaning the item has scrolled into view | |
let itemAboveBottom = itemTop <= windowBottomPosition; | |
// If item is in view then parallax it at the given speed/rotation | |
// In view is top of the item has peaked into the bottom of the frame and bottom of the item is just about to leave top of frame | |
if(itemBelowTop && itemAboveBottom) { | |
// User configurations for speed and rotate | |
let speed = Number(item.dataset.speed); | |
let rotate = Number(item.dataset.rotate); | |
// Calculate the percentage the item has scrolled within the viewport | |
// If item was already in viewport then subtract its base so we have an origin for the scroll effects | |
let percentage = (windowHeight - item.getBoundingClientRect().top) / (windowHeight + item.clientHeight) - item.base; | |
let rawPosition = (speed * (percentage * 100)); | |
let position = Math.round(rawPosition * 10) / 10; | |
// Rotate a specific amount of degrees while item is in viewport | |
let rawDegrees = (rotate/100) * (percentage * 100); | |
let degrees = Math.round(rawDegrees * 10) / 10; | |
// Check which data attributes the user has set | |
if(rotate && speed) { | |
item.style.transform = 'translate3d(0, -' + position + 'px, 0) rotate(' + degrees + 'deg)'; | |
} | |
else if(rotate) { | |
item.style.transform = 'rotate(' + degrees + 'deg)'; | |
} | |
else if(speed) { | |
item.style.transform = 'translate3d(0, -' + position + 'px, 0)'; | |
} | |
} | |
}); | |
} | |
// Only trigger parallax effect on certain screen sizes. | |
if(mq.matches) { | |
window.addEventListener('scroll', function(){ | |
// Ensure the browser repaints before running each animation | |
window.requestAnimationFrame(checkParallaxItems); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment