Custom Image Carousel
Wanted to experiment with this prototype of image slicing and combining the pieces together to create the full image in a slider.
A Pen by Jarrod Thibodeau on CodePen.
Wanted to experiment with this prototype of image slicing and combining the pieces together to create the full image in a slider.
A Pen by Jarrod Thibodeau on CodePen.
div#app | |
span(onclick="changePosition(-1)") ← | |
div#theImage | |
span(onclick="changePosition(1)") → |
const images = [ | |
"https://s3-us-west-2.amazonaws.com/s.cdpn.io/394353/supermario.jpg", | |
"https://s3-us-west-2.amazonaws.com/s.cdpn.io/394353/donkeykong.jpg", | |
"https://s3-us-west-2.amazonaws.com/s.cdpn.io/394353/waluigi.jpg" | |
]; | |
const X_CHANGE = 1000; | |
const Y_CHANGE = 1000; | |
const BACKGROUND_POS_PERCENT = 11.1; | |
const TIMER_INTERVAL = 2250; | |
const IMAGE_PIECE_COUNT = 10; | |
const ROTATION = 25; | |
let indy = 0; | |
let isChanging = false; | |
function removeImage() { | |
return new Promise((resolve, reject) => { | |
for (let i = 0; i < IMAGE_PIECE_COUNT; i++) { | |
const chunk = document.getElementById(`chunk${i}`); | |
TweenMax.to(chunk, 1, { | |
rotation: ROTATION, | |
ease: Strong.easeInOut, | |
onComplete: () => { | |
TweenMax.fromTo( | |
chunk, | |
1, | |
{ x: 0, y: 0 }, | |
{ | |
y: i % 2 === 0 ? -Y_CHANGE : Y_CHANGE, | |
x: i % 2 === 0 ? -X_CHANGE : X_CHANGE, | |
ease: Strong.easeInOut, | |
onComplete: () => { | |
chunk.parentNode.removeChild(chunk); | |
resolve(true); | |
} | |
} | |
); | |
} | |
}); | |
} | |
}); | |
} | |
function displayImage(index) { | |
const src = images[index]; | |
const image = document.getElementById("theImage"); | |
let pos = 0; | |
for (let i = 0; i < IMAGE_PIECE_COUNT; i++) { | |
const chunk = document.createElement("div"); | |
chunk.id = `chunk${i}`; | |
chunk.style.background = `url('${src}')`; | |
chunk.style.backgroundPosition = `${pos}% ${pos}%`; | |
chunk.style.height = "40px"; | |
chunk.style.width = "400px"; | |
pos += BACKGROUND_POS_PERCENT; | |
theImage.appendChild(chunk); | |
TweenMax.fromTo( | |
chunk, | |
1, | |
{ | |
x: i % 2 === 0 ? -X_CHANGE : X_CHANGE, | |
y: i % 2 === 0 ? Y_CHANGE : -Y_CHANGE, | |
rotation: -ROTATION | |
}, | |
{ | |
y: 0, | |
x: 0, | |
ease: Strong.easeInOut, | |
onComplete: () => { | |
TweenMax.to(chunk, 1, { | |
rotation: 0, | |
ease: Strong.easeInOut, | |
onComplete: () => isChanging = false | |
}); | |
} | |
} | |
); | |
} | |
} | |
function changePosition(movement) { | |
//To ensure that switching does not happen if a switch is already happening | |
if (!isChanging) { | |
if (indy + movement < 0) { | |
indy = images.length - 1; | |
} else if (indy + movement > images.length - 1) { | |
indy = 0; | |
} else { | |
indy += movement; | |
} | |
isChanging = true; | |
removeImage().then(() => displayImage(indy)); | |
} | |
} | |
window.onload = () => { | |
displayImage(indy); | |
}; |
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js"></script> |
html, body { | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
flex-direction: column; | |
height: 100%; | |
overflow: hidden; | |
} | |
#app { | |
display: flex; | |
font-size: 100px; | |
justify-content: center; | |
align-items: center; | |
} | |
#app > span { | |
padding: 30px; | |
} | |
#app > span:hover { | |
cursor: pointer; | |
} | |
#theImage { | |
display: flex; | |
flex-flow: row wrap; | |
height: 400px; | |
width: 400px; | |
background-repeat: none; | |
} | |
#buttons { | |
position: absolute; | |
bottom: 20px; | |
} |