MetatronLatestWebsite/src/components/home/CounterAreaThree.tsx
2026-03-06 16:23:38 +05:30

108 lines
3.2 KiB
TypeScript

"use client";
import React, { useState, useEffect, useRef } from 'react';
interface CounterProps {
end: number;
duration?: number;
}
const Counter: React.FC<CounterProps> = ({ end, duration = 2000 }) => {
const [count, setCount] = useState(0);
const countRef = useRef<HTMLSpanElement>(null);
const [hasStarted, setHasStarted] = useState(false);
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setHasStarted(true);
} else {
setHasStarted(false);
setCount(0);
}
},
{ threshold: 0.1 }
);
if (countRef.current) {
observer.observe(countRef.current);
}
return () => observer.disconnect();
}, []);
useEffect(() => {
if (!hasStarted) return;
let startTimestamp: number | null = null;
let animationFrameId: number;
const step = (timestamp: number) => {
if (!startTimestamp) startTimestamp = timestamp;
const progress = Math.min((timestamp - startTimestamp) / duration, 1);
setCount(Math.floor(progress * end));
if (progress < 1) {
animationFrameId = window.requestAnimationFrame(step);
}
};
animationFrameId = window.requestAnimationFrame(step);
return () => window.cancelAnimationFrame(animationFrameId);
}, [hasStarted, end, duration]);
return <span ref={countRef}>{count}</span>;
};
const counterItems = [
{
icon: "/assets/images/about/2/projects.webp",
count: 100,
suffix: "+",
text: "Projects Completed"
},
{
icon: "/assets/images/about/2/active.webp",
count: 50,
suffix: "+",
text: "Active Clients"
},
{
icon: "/assets/images/about/2/expert.webp",
count: 20,
suffix: "+",
text: "Expert People"
},
{
icon: "/assets/images/about/2/happy.webp",
count: 50,
suffix: "+",
text: "Happy Clients"
}
];
const CounterAreaThree: React.FC = () => {
return (
<section className="counter-area-three">
<div className="container">
<ul className="counter-area-three__list">
{counterItems.map((item, index) => (
<li key={index} className="counter-area-three__item count-box">
<div className="counter-area-three__icon">
<img src={item.icon} alt="icon" />
</div>
<div className="counter-area-three__content">
<h3 className="counter-area-three__count">
<Counter end={item.count} />
{item.suffix}
</h3>
<p className="counter-area-three__text">{item.text}</p>
</div>
</li>
))}
</ul>
</div>
</section>
);
};
export default CounterAreaThree;