I'm trying to replicate apple's image sequencing animation - https://www.apple.com/airpods-pro/. I've managed to track down a few examples and they all work great but they all trigger at the top of the page and I want mine to trigger in the middle of the page. I've tried attaching the trigger event to the #graphHolder container but it still starts cycling through the images as soon as you scroll at the top of the page. Can anyone point to where I'm going wrong? Here's a jsfiddle - https://jsfiddle.net/mvyw2bc3/2/
const html = document.documentElement;
const canvas = document.getElementById("hero-lightpass");
const context = canvas.getContext("2d");
const frameCount = 132;
const currentFrame = index => ( `https://res.cloudinary.com/icebreakernz/image/upload/v1623273037/globalcampaign/plastic-free/sequence-test/IB-Graph_Animation${index.toString().padStart(4, '0')}.jpg`
)
const preloadImages = () => {
for (let i = 1; i < frameCount; i++) {
const img = new Image();
img.src = currentFrame(i);
}
};
const img = new Image()
img.src = currentFrame(1);
canvas.width=1920;
canvas.height=1080;
img.onload=function(){
context.drawImage(img, 0, 0);
}
const updateImage = index => {
img.src = currentFrame(index);
context.drawImage(img, 0, 0);
}
window.addEventListener('scroll', () => {
const scrollTop = html.scrollTop;
const maxScrollTop = html.scrollHeight - window.innerHeight;
const scrollFraction = scrollTop / maxScrollTop;
const frameIndex = Math.min(
frameCount - 1,
Math.ceil(scrollFraction * frameCount)
);
requestAnimationFrame(() => updateImage(frameIndex + 1))
});
preloadImages()
For anyone that runs in to the same problem, I ended up going with ScrollTrigger which made it super simple. Check out my fiddle here to see it working as it should - https://jsfiddle.net/jdrebugL/
const canvas = document.getElementById("hero-lightpass");
const context = canvas.getContext("2d");
canvas.width = 1920;
canvas.height = 1080;
const frameCount = 132;
const currentFrame = index => ( `https://res.cloudinary.com/icebreakernz/image/upload/v1623273037/globalcampaign/plastic-free/sequence-test/IB-Graph_Animation${(index + 1).toString().padStart(4, '0')}.jpg`
);
const images = []
const airpods = {
frame: 0
};
for (let i = 0; i < frameCount; i++) {
const img = new Image();
img.src = currentFrame(i);
images.push(img);
}
gsap.to(airpods, {
frame: frameCount - 1,
snap: "frame",
scrollTrigger: {
scrub: 1,
trigger: "#hero-lightpass",
start: "top top",
pin: true
},
onUpdate: render // use animation onUpdate instead of scrollTrigger's onUpdate
});
images[0].onload = render;
function render() {
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(images[airpods.frame], 0, 0);
}