2026-03-03 21:33:01 +05:30

103 lines
3.0 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 && !hasStarted) {
setHasStarted(true);
}
},
{ threshold: 0.1 }
);
if (countRef.current) {
observer.observe(countRef.current);
}
return () => observer.disconnect();
}, [hasStarted]);
useEffect(() => {
if (!hasStarted) return;
let startTimestamp: number | null = null;
const step = (timestamp: number) => {
if (!startTimestamp) startTimestamp = timestamp;
const progress = Math.min((timestamp - startTimestamp) / duration, 1);
setCount(Math.floor(progress * end));
if (progress < 1) {
window.requestAnimationFrame(step);
}
};
window.requestAnimationFrame(step);
}, [hasStarted, end, duration]);
return <span ref={countRef}>{count}</span>;
};
const counterItems = [
{
icon: "/assets/imgs/icon/icon-1.png",
count: 950,
suffix: "k+",
text: "Projects Succefull"
},
{
icon: "/assets/imgs/icon/icon-2.png",
count: 256,
suffix: "k+",
text: "Happy Customers"
},
{
icon: "/assets/imgs/icon/icon-3.png",
count: 852,
suffix: "k+",
text: "Consultants Planing"
},
{
icon: "/assets/imgs/icon/icon-4.png",
count: 965,
suffix: "+",
text: "Awards Winners"
}
];
const CounterAreaTwo: React.FC = () => {
return (
<section className="counter-area-two">
<div className="container">
<ul className="counter-area-two__list">
{counterItems.map((item, index) => (
<li key={index} className="counter-area-two__item count-box">
<div className="counter-area-two__icon">
<img src={item.icon} alt="icon" />
</div>
<div className="counter-area-two__content">
<h3 className="counter-area-two__count">
<Counter end={item.count} />
{item.suffix}
</h3>
<p className="counter-area-two__text">{item.text}</p>
</div>
</li>
))}
</ul>
</div>
</section>
);
};
export default CounterAreaTwo;