3

I have some problem animating my progress bar component ... I am trying to animate my component (by filling the progress bar component width from 0% to X% with a Spring when it is visible on the screen (by using VisibilitySensor). I have tried a few things so far and I did not figure out how to do it properly yet. PS: I am currently a newbie with React.

Here's what I have tried so far :

Attempt # 1: -Problem with this approach: I get an error saying "Interpolation is not defined" (probably because of width: isVisible ? ${props.percent}% : '0%' in the Spring) Maybe there is a workaround this ?

function SkillProgress(props) {
    return (
        <VisibilitySensor>
            {({ isVisible }) => (
                <Spring delay={300} to={{ opacity: isVisible ? 1 : 0, width: isVisible ? `${props.percent}%` : '0%'}}>
                    {animation =>
                        <div>
                            <div>{props.icon}{props.skillname}</div>
                            <div className={"progressbar"}>
                                <div className={"progressbarprg"} style={animation}><span
                                    className={"skillLevel"}>{props.level}</span></div>
                            </div>
                        </div>
                    }
                </Spring>
            )}
        </VisibilitySensor>
    )
}

Attempt # 2 :

Problem with this approach : The initial animation works but when the component goes from visible to not visible the spring animation does not work, it goes directly from 0% to X%.

function SkillProgress(props) {
const spring = useSpring({from: {width: '0%'}, width: ${props.percent}%, config: config.molasses, delay: 300});
const spring2 = useSpring({from: {width: ${props.percent}%}, width: '0%', config: config.molasses, delay: 300});

return (
    <VisibilitySensor>
        {({ isVisible }) => (
            <div>
                <div>{props.icon}{props.skillname}</div>
                <div className={"progressbar"}>
                    <animated.div className={"progressbarprg"} style={isVisible ? spring : spring2}><span
                        className={"skillLevel"}>{props.level}</span></animated.div>
                </div>
            </div>
        )}
    </VisibilitySensor>
)
}

Thank you in advance for your help !

GBab
  • 31
  • 1
  • 2
  • 1
    I added the code on codesandbox so you guys can see what I am trying to achieve. It kinda works but I need the width in % not in px ... Have a look : https://codesandbox.io/s/88ok0rqw2l – GBab Apr 03 '19 at 12:05

1 Answers1

1

In your first attempt it definitely does not like interpolating between string values, this may be down to the older render props API for react-spring but I'm honestly not too sure about the explanation there.

In your second attempt I believe it's because of mixing a render prop API for VisibilitySensor and hooks API for react-spring and the state of isVisible not being captured anywhere.

I had a play around and this is a working version which I think is what you're looking for https://codesandbox.io/s/wnyx6vp348

function SkillProgress(props) {
  const [isInView, setIsInView] = React.useState(false);

  const onVisibilityChange = isInView => setIsInView(isInView);

  const progressSpringStyleProps = useSpring({
    width: isInView ? `${props.percent}%` : `0%`,
    config: config.molasses
  });

  return (
    <VisibilitySensor onChange={onVisibilityChange}>
      <div>
        <div>{props.skillname}</div>
        <div className={"progressbar"}>
          <animated.div
            className={"progressbarprg"}
            style={progressSpringStyleProps}
          />
        </div>
      </div>
    </VisibilitySensor>
  );
}
sanjsanj
  • 1,003
  • 9
  • 20