From 30a5f936e1bf73e823542b9e9b6bcb5940f5d3c0 Mon Sep 17 00:00:00 2001 From: MU AHMED <145216818+Rony-2004@users.noreply.github.com> Date: Thu, 27 Feb 2025 14:10:17 +0530 Subject: [PATCH] Timeline.jsx --- src/Components/Timeline/Timeline.jsx | 99 +++++++++++++++------------- 1 file changed, 54 insertions(+), 45 deletions(-) diff --git a/src/Components/Timeline/Timeline.jsx b/src/Components/Timeline/Timeline.jsx index d2336da..7681237 100644 --- a/src/Components/Timeline/Timeline.jsx +++ b/src/Components/Timeline/Timeline.jsx @@ -1,5 +1,6 @@ -import React, { useEffect, useState, useRef } from 'react'; -import { motion, useAnimation } from 'framer-motion'; +import React, { useEffect } from 'react'; +import { motion, useAnimation, useInView } from 'framer-motion'; +import { useRef } from 'react'; import './Timeline.css'; const timelineData = [ @@ -11,25 +12,44 @@ const timelineData = [ const TimelineItem = ({ event, index, activeIndex }) => { const ref = useRef(null); + const isInView = useInView(ref, { once: false, margin: "-100px" }); const controls = useAnimation(); useEffect(() => { - if (index === activeIndex) { - controls.start({ opacity: 1, y: 0, scale: 1 }); + if (isInView) { + controls.start("visible"); } else { - controls.start({ opacity: 0.5, y: 50, scale: 0.9 }); + controls.start("hidden"); } - }, [activeIndex, index, controls]); + }, [isInView, controls]); + + const variants = { + hidden: { + opacity: 0, + y: 100, + scale: 0.8, + transition: { duration: 0.1 } + }, + visible: { + opacity: 1, + y: 0, + scale: 1, + transition: { duration: 0.1 } + } + }; return ( index ? 0.3 : 1 + }} > -
+
{event.date} @@ -42,60 +62,49 @@ const TimelineItem = ({ event, index, activeIndex }) => { }; const Timeline = () => { - const [activeIndex, setActiveIndex] = useState(0); + const [activeIndex, setActiveIndex] = React.useState(0); const containerRef = useRef(null); - const scrollTimeout = useRef(null); // Prevent frequent updates useEffect(() => { const handleScroll = () => { if (!containerRef.current) return; - if (scrollTimeout.current) { - clearTimeout(scrollTimeout.current); - } - - scrollTimeout.current = setTimeout(() => { - requestAnimationFrame(() => { - const items = containerRef.current.querySelectorAll('.timeline-item'); - const viewportMiddle = window.innerHeight / 2; - let newIndex = 0; + const items = containerRef.current.querySelectorAll('.timeline-item'); + const containerTop = containerRef.current.offsetTop; + const scrollPosition = window.scrollY + window.innerHeight / 2; - items.forEach((item, index) => { - const rect = item.getBoundingClientRect(); - const itemMiddle = rect.top + rect.height / 2; - if (itemMiddle < viewportMiddle) { - newIndex = index; - } - }); - - // Prevent unnecessary updates - if (newIndex !== activeIndex) { - setActiveIndex(newIndex); - } - }); - }, 100); // Smooth delay + items.forEach((item, index) => { + const itemTop = item.offsetTop + containerTop; + if (scrollPosition > itemTop) { + setActiveIndex(index); + } + }); }; - window.addEventListener('scroll', handleScroll, { passive: true }); - return () => { - window.removeEventListener('scroll', handleScroll); - clearTimeout(scrollTimeout.current); - }; - }, [activeIndex]); + window.addEventListener('scroll', handleScroll); + return () => window.removeEventListener('scroll', handleScroll); + }, []); return (
-

Timeline

+

Timeline

{/* Added heading */}
-
+ {timelineData.map((event, index) => ( - + ))}