Files
Portfolio/src/portfolio/helpers/ProgressBar.tsx

77 lines
1.8 KiB
TypeScript

import { FC, MutableRefObject, useEffect, useRef, useState } from "react";
type ProgressBarArgs = {
percentage : number,
customScore? : string,
}
const ProgressBar : FC<ProgressBarArgs> = ({ percentage,customScore }): JSX.Element => {
const ref = useRef<HTMLDivElement>() as MutableRefObject<HTMLDivElement>;
const onScreen = useOnScreen(ref);
const [current,setCurrent] = useState(0);
useEffect(() => {
if (onScreen && current==0)
{
let counter = 0;
const id = setInterval(() => {
if (counter<percentage*2)
{
counter += (percentage/100);
setCurrent(counter);
}
else {
if (counter>percentage*2)
{
setCurrent(percentage*2);
}
clearInterval(id);
}
},25);
}
},[onScreen, current, percentage]);
return (
<div className={"pBContainer"} ref={ref}>
<div className={"progressBar"}>
<div className={"inner"} style={{ width : `${current/2}%` }}></div>
</div>
<div className={"below"} style={{ width : customScore? "100%" : `${current/2}%`, textAlign: "right" }}>{customScore? customScore : Math.ceil(current/2)+"%"}</div>
</div>
);
};
function useOnScreen(ref : MutableRefObject<HTMLDivElement>, rootMargin = "0px"): boolean {
// State and setter for storing whether element is visible
const [isIntersecting, setIntersecting] = useState(false);
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
// Update our state when observer callback fires
setIntersecting(entry.isIntersecting);
},
{
rootMargin
}
);
const currentRef = ref.current;
if (currentRef) {
observer.observe(currentRef);
}
return () => {
if (currentRef) {
try {
observer.unobserve(currentRef);
}
catch {
// Observer failure handled silently
}
}
};
}, [ref, rootMargin]);
return isIntersecting;
}
export default ProgressBar;