2021-12-09

Tech Programing

程式人小天地

Fill div up to given percentage horizontally with animation

1 min read


I’ve been trying to create this React component and I’m having problems with text wrapping. I want to have a rectangle that fills up to a given percentage of the width after the user clicks on it, and have it ease in. Basically, I want to create this (without the text animation): Dribbble mockup of desired effect.

The problem: So far, I haven’t been able to achieve this without setting a fixed height on the bar, which makes the text inside overflow if it’s too long.

Things I’ve tried include having a linear gradient background that eases in, though that seems complicated since I’m not animating it to a consistent % width.

What currently works for me is having a wrapper div that’s absolutely positioned and having another div with a z-index -10 underneath it, which is the same height. Then I have another React component inside that handles the animation. Here’s my code (I use Tailwind CSS but I could use custom CSS if needed):

function Card(props) {

  const percentage = Math.round(choice.choice_votes / total * 100)

  return (
    <div className="w-full relative h-16 sm:h-14 mb-3">
      <div className="w-full absolute h-16 sm:h-14 flex justify-between items-center border border-pink-500 px-6 py-2 rounded-xl">
        <div className="flex">
          <p className="text-sm sm:text-base"> TEXT THAT NEEDS TO BE WRAPPED HERE </p>
          <div className="flex items-center px-3">
            <BsCheckCircleFill size={16} color="#d1f400" />
          </div>
        </div>
        <div>
          <p className="text-xs sm:text-sm font-bold w-12 text-right"> { percentage }% </p>
        </div>
      </div>
      <div className={"absolute -z-10 h-full w-full rounded-xl"}>
        <Filler value={percentage} />
      </div>
    </div>
  )
}

function Filler(props) {
  const { value } = props
  const [width, setWidth] = useState(0)

  useEffect(() => {
    requestAnimationFrame(() => {
      setWidth(value)
    })
  }, [value])

  return (
    <div className={"filler h-full rounded-xl bg-primary transition-width ease-in duration-700 flex items-center justify-start"}
    style={{ width: `${width}%` }} >
    </div>
  )
}

I would be so grateful for any help with figuring out how to make these bar heights expand to fit any arbitrary length text and still be able to achieve that fill-in effect. Thank you so much!



Source link

資料來源:Stackoverflow

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *