Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help with playSegments #67

Open
jordanlambrecht opened this issue Jul 11, 2022 · 7 comments
Open

Help with playSegments #67

jordanlambrecht opened this issue Jul 11, 2022 · 7 comments

Comments

@jordanlambrecht
Copy link

I'm trying to have my lottie animation play the first 23 frames, and then skip them when it loops back and restarts and play frames 24-95 indefinitely. I'm dumb and can't seem to figure out how to make this work. Example here of it implemented with react-lottie-player (I'm switching over because you're more active and cool)

Here's my code that isn't working:

function PageHeader_VariableHeight() {
  const playFrames = {
    segments: [
      [0, 23],
      [24, 95],
    ],
    forceFlag: false,
  }
  const LottieAnimation = () => {
    const [animationData, setAnimationData] = useState(undefined)
    useEffect(() => {
      import('@data/Patterns_Peach.json').then(setAnimationData)
    }, [])

    if (!animationData)
      return (<p> Loading</p>)
    return (
      <Lottie
        animationData={animationData}
        loop={true}
        playSegments={playFrames}
        autoplay={true}
        rendererSettings={{ preserveAspectRatio: 'xMidYMid slice' }}
        style={{ height: '100%' }}
      />
    )
  }
  return (
      <LottieAnimation />
  )
}
export default PageHeader_VariableHeight
@jordanlambrecht
Copy link
Author

@Gamote Any ideas?

@jordanlambrecht
Copy link
Author

@michax @mattvague @PatrickDesign Sorry for the pings, but this is pretty mission-critical for me

@PatrickDesign
Copy link
Contributor

PatrickDesign commented Aug 8, 2022

In what way is it not working?

I'm assuming the fact that you're defining a react component within another react component and using dynamic imports doesn't cause the issue.

@jordanlambrecht
Copy link
Author

@PatrickDesign Ha, I probably need to separate those components o.O The animation will play just fine. Everything works with no errors. The only issue is the segments part. It simply does not listen to the input and plays the whole animation straight through each loop.

@PatrickDesign
Copy link
Contributor

PatrickDesign commented Aug 8, 2022

Could you use the onLoopComplete method to update your segment array to be the shortened one after the first loop? And use the initialSegment prop instead of playSegments.

Something like:

// Defined statically outside of any functions (to keep a stable reference https://lottiereact.com/#initialsegment)
const firstLoopSegment = [0, 23]
const secondLoopSegment = [24, 95]

...

const [activeSegment, setActiveSegment] = useState(firstLoopSegment)

const onLoopComplete = () => {
  setActiveSegment(secondLoopSegment)
}

...

<Lottie onLoopComplete={onLoopComplete} initialSegment={activeSegment} ... />

@jordanlambrecht
Copy link
Author

Like this? Because no dice if so =/

import lottie from 'lottie-web'

interface LottieProps {
  animationData: any
  width: number
  height: number
  onLoopComplete: any
  initialSegment: any
}

const firstLoopSegment = [0, 23]
const secondLoopSegment = [24, 95]

const Lottie = ({ animationData }: LottieProps) => {
  const element = useRef<HTMLDivElement>(null)
  const lottieInstance = useRef<any>()

  useEffect(() => {
    if (element.current) {
      lottieInstance.current?.destroy()
      lottieInstance.current = lottie.loadAnimation({
        container: element.current,
        renderer: 'svg',
        loop: true,
        autoplay: true,

        rendererSettings: {
          preserveAspectRatio: 'xMidYMid slice',
        },
        animationData: animationData,
      })
    }
    return () => {
      lottieInstance.current?.destroy()
      lottieInstance.current = null
    }
  }, [animationData])

  return <div style={{ height: '100%', width: '100%' }} ref={element} />
}

const PageHeader_VariableHeight = ({ animationData }) => {
  const [activeSegment, setActiveSegment] = useState(firstLoopSegment)
  const onLoopComplete = () => {
    setActiveSegment(secondLoopSegment)
  }

  return (
    <Lottie
      animationData={animationData}
      width={100}
      height={100}
      onLoopComplete={onLoopComplete}
      initialSegment={activeSegment}
    />
  )
}
export default PageHeader_VariableHeight

@jordanlambrecht
Copy link
Author

AHA! I got it!

import lottie from 'lottie-web'

interface LottieProps {
  animationData: any
  width: number
  height: number
}

const Lottie = ({ animationData }: LottieProps) => {
  const element = useRef<HTMLDivElement>(null)
  const lottieInstance = useRef<any>()

  useEffect(() => {
    if (element.current) {
      lottieInstance.current?.destroy()
      lottieInstance.current = lottie.loadAnimation({
        container: element.current,
        renderer: 'svg',
        loop: true,
        // autoplay: true,

        rendererSettings: {
          preserveAspectRatio: 'xMidYMid slice',
        },
        animationData: animationData,
      })
    }
    lottieInstance.current.playSegments(
      [
        [0, 23],
        [24, 95],
      ],
      true,
    )
    return () => {
      lottieInstance.current?.destroy()
      lottieInstance.current = null
    }
  }, [animationData])

  return <div style={{ height: '100%', width: '100%' }} ref={element} />
}

const PageHeader_VariableHeight = ({ animationData }) => {
  return <Lottie animationData={animationData} width={100} height={100} />
}
export default PageHeader_VariableHeight

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants