简体   繁体   中英

How to preserve aspect ratio upon resizing browser containing a react-lottie component?

I have a Lottie animation that is rendered using react-lottie ( https://www.npmjs.com/package/react-lottie )

import Lottie from 'react-lottie'
import animationData from './path/to/animation.json'

const MyComponent = () => {
    const myOptions = {
        loop: true,
        autoplay: true,
        renderer: 'canvas',
        animationData: animationData
    }

    return (
        <div>
            ...other stuff
            <Lottie options={myOptions} width={1000} height={500} />
        </div>
    )
}

The animation displays and plays fine.

The issue is that when resizing the browser, the animation shrinks and squishes and does not preserve its original aspect ratio. If I do a page refresh after shrinking the browser, the animation is then rendered correctly. It is only when the resizing is actively occurring that the aspect ratio is off.

I have tried adding:

rendererSettings: {
    preserveAspectRatio: 'xMidYMid slice' // also tried 'xMidYMid meet'
}

to my options but that does not work either.

The only other thing I can think of is to attach a resize event listener to the window which will in turn call lottie.resize()

useEffect(() => {
    window.addEventListener('resize', ??)
}, [])

The stuff in ?? is where I get stuck. I know that using lottie-web , I have direct access to a lottie.resize() function. However, when using react-lottie , how do I call/access the resize function?

Any help would be greatly appreciated.

Edit: I have been asked to add an example animation JSON so it is here: https://pastebin.com/gXCEhKaR

Yes, thank you, I started it at home, but you have the width and height values set for the Lottie component. If you want Lottie to change its size depending on the size of the screen, then you need to add a hook to change the screen.

Hook resize

  export function useSizeComponents (ref) {
  const [size, setSize] = useState([0, 0])

  useLayoutEffect(() => {
    function updateSize () {
      let newSize = [window.innerWidth, window.innerHeight]
      if (ref?.current) {
        newSize = [ref.current.offsetWidth, ref.current.offsetHeight]
      }
      setSize(newSize)
    }
    window.addEventListener('resize', updateSize)
    updateSize()
    return () => window.removeEventListener('resize', updateSize)
  }, [])

  return size
}

Your component

const MyComponent = () => {
  const [width, height] = useSizeComponents()
  const scaleLottie = 0.5

  const myOptions = {
    loop: true,
    autoplay: true,
    renderer: 'canvas',
    animationData: animationData,
  }

  const control = useMemo(() => {
    if (!width) return null
    const xMidYMid = 0.5
    const sizeComponent = {
      width: width * scaleLottie,
      height: width * scaleLottie * xMidYMid
    }
    return <Lottie key={width} options={myOptions} {...sizeComponent} />
  }, [width])

  return (
    <div>
      ...other stuff
      {control}
    </div>
  )
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM