@jeremyckahn/farmhand
Version:
A farming game
73 lines (62 loc) • 1.91 kB
JavaScript
import React, { useState, useEffect } from 'react'
import { number } from 'prop-types'
import { interpolate, tween } from 'shifty'
import './ProgressBar.sass'
const incompleteColor = '#ff9f00'
const completeColor = '#00e500'
const ProgressBar = ({ percent }) => {
const [displayedProgress, setDisplayedProgress] = useState(0)
const [displayedColor, setDisplayedColor] = useState(incompleteColor)
/** @type {[import('shifty').Tweenable | undefined, React.Dispatch<React.SetStateAction<import('shifty').Tweenable | undefined>>]} */
const [currentTweenable, setCurrentTweenable] = useState()
useEffect(() => {
if (!currentTweenable) {
const tweenable = tween({
delay: 750,
easing: 'easeInOutQuad',
duration: 1500,
from: { currentPercent: 0 },
to: { currentPercent: percent },
render: ({ currentPercent }) => {
const currentPercentNumber = Number(currentPercent)
setDisplayedProgress(Number(currentPercentNumber.toFixed(2)))
setDisplayedColor(
interpolate(
{ color: incompleteColor },
{ color: completeColor },
currentPercentNumber / 100
).color
)
},
})
setCurrentTweenable(tweenable)
}
return () => {
if (currentTweenable) {
currentTweenable.cancel()
}
}
}, [currentTweenable, percent])
return (
<div className="ProgressBar">
<div {...{ className: 'progress-wrapper' }}>
<div
{...{
className: 'progress',
style: {
background: displayedColor,
width: `${displayedProgress}%`,
},
}}
></div>
</div>
<p>
<span>{displayedProgress}%</span>
</p>
</div>
)
}
ProgressBar.propTypes = {
percent: number.isRequired,
}
export default ProgressBar