testing
function resize(){
const dpr=devicePixelRatio||1;
canvas.width=innerWidth*dpr;
canvas.height=innerHeight*dpr;
canvas.style.width=innerWidth+"px";
canvas.style.height=innerHeight+"px";
ctx.setTransform(dpr,0,0,dpr,0,0);
drawFrame(currentFrame);
}
window.addEventListener("resize",resize);
frameNames.forEach((src,i)=>{
let img=new Image();
img.src=src;
img.onload=()=>{
images[i]=img;
loaded++;
if(loaded===frameNames.length){
resize();
drawFrame(0);
startAnimation();
}
}
});
function drawFrame(index){
if(!images[index])return;
currentFrame=index;
let img=images[index];
let w=canvas.width/(devicePixelRatio||1);
let h=canvas.height/(devicePixelRatio||1);
ctx.clearRect(0,0,w,h);
let scale=Math.min(
w/img.width,
h/img.height
);
let width=img.width*scale;
let height=img.height*scale;
ctx.drawImage(
img,
(w-width)/2,
(h-height)/2,
width,
height
);
}
function toggleHotspots(show){
hotspots.forEach(h=>{
gsap.to(h,{
opacity:show?1:0,
scale:show?1:0,
duration:.3
});
});
}
function startAnimation(){
gsap.to(sequence,{
frame:lastFrame,
snap:"frame",
ease:"none",
scrollTrigger:{
trigger:".sequence-section",
start:"top top",
end:"bottom bottom",
scrub:.5,
onUpdate:()=>{
let frame=Math.round(sequence.frame);
drawFrame(frame);
// ONLY SHOW ON LAST IMAGE
if(frame===lastFrame){
toggleHotspots(true);
}
else{
toggleHotspots(false);
infoCard.classList.remove("show");
}
}
}
});
}
hotspots.forEach(h=>{
h.addEventListener("mouseenter",()=>{
if(currentFrame!==lastFrame)return;
let data=hotspotInfo[h.id];
cardImage.src=data.image;
cardTitle.textContent=data.title;
cardDescription.textContent=data.description;
let rect=h.getBoundingClientRect();
infoCard.style.left=(rect.left+30)+"px";
infoCard.style.top=(rect.top-30)+"px";
infoCard.classList.add("show");
});
h.addEventListener("mouseleave",()=>{
infoCard.classList.remove("show");
});
});
ScrollTrigger.refresh();