Skip to content

Instantly share code, notes, and snippets.

@lgastler
Last active September 21, 2022 08:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lgastler/33c4aef88e336da0bd9b1d5da4782a76 to your computer and use it in GitHub Desktop.
Save lgastler/33c4aef88e336da0bd9b1d5da4782a76 to your computer and use it in GitHub Desktop.
import {
AnimatePresence,
motion,
useScroll,
useTransform,
} from "framer-motion";
import { useEffect, useRef, useState } from "react";
export default function HomePage() {
const stopAmount = 8;
const imageWidth = 1280;
const imageHeight = 320;
const imageRef = useRef(null);
const { scrollXProgress } = useScroll({
container: imageRef,
});
const items = [
{
sectors: [0, 1, 2],
title: "Item 0",
},
{
sectors: [1, 2],
title: "Item 1",
},
{
sectors: [2, 3, 4, 5],
title: "Item 2",
},
{
sectors: [3, 4],
title: "Item 3",
},
{
sectors: [2, 3, 4, 5, 6],
title: "Item 4",
},
{
sectors: [5],
title: "Item 5",
},
{
sectors: [5, 6, 7],
title: "Item 6",
},
{
sectors: [6, 7],
title: "Item 7",
},
{
sectors: [7, 8],
title: "Item 8",
},
];
const [visibleItems, setVisibleItems] = useState(
items.filter((item) => item.sectors.includes(0))
);
const distance = useTransform(scrollXProgress, [0, 1], [0, stopAmount]);
function update() {
const currenctSector = Math.floor(distance.get());
const newItems = items.filter((item) =>
item.sectors.includes(currenctSector)
);
setVisibleItems(newItems);
}
useEffect(() => {
return distance.onChange(() => update());
});
return (
<motion.div>
<div className="w-full">
<div
className="relative flex snap-x snap-mandatory overflow-x-auto"
style={{ scrollbarWidth: "none", height: imageHeight }}
ref={imageRef}
>
<div
className="absolute inset-0 bg-city"
style={{ width: imageWidth }}
></div>
{Array.from(Array(stopAmount).keys()).map((i) => (
<div className="shrink-0 snap-start ">
<div style={{ width: `${imageWidth / stopAmount}px` }} />
</div>
))}
</div>
</div>
<div className="space-y-2 px-12 py-8">
<AnimatePresence mode="popLayout">
{visibleItems.map((i) => (
<motion.div
whileHover={{ scale: 1.05 }}
key={i.title}
layout
initial={{ scale: 0.9, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
exit={{ scale: 0.9, opacity: 0 }}
transition={{ duration: 1 }}
>
<div className="flex h-16 w-full items-center justify-center rounded-xl bg-pink-500 text-center text-white">
<p className="font-mono text-3xl">{i.title}</p>
</div>
</motion.div>
))}
</AnimatePresence>
</div>
</motion.div>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment