Как сохранить соотношение сторон при изменении размера браузера, содержащего компонент react-lottie?

#reactjs #lottie

Вопрос:

У меня есть анимация Лотти, которая визуализируется с использованием 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>
    )
}
 

Анимация отображается и воспроизводится нормально.

Проблема в том, что при изменении размера браузера анимация сжимается и сжимается и не сохраняет свое первоначальное соотношение сторон. Если я обновлю страницу после сжатия браузера, анимация будет отображаться правильно. Только при активном изменении размера соотношение сторон отключается.

Я попытался добавить:

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

к моим вариантам, но это тоже не работает.

Единственное, о чем я могу подумать, это прикрепить прослушиватель resize событий к окну, которое, в свою очередь, вызовет lottie.resize()

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

Все дело в ?? том, где я застрял. Я знаю , что при использовании lottie-web у меня есть прямой доступ к lottie.resize() функции. Однако при использовании react-lottie , как я могу вызвать/получить доступ к функции изменения размера?

Любая помощь была бы очень признательна.

Редактировать: Меня попросили добавить пример анимации JSON, поэтому он здесь: https://pastebin.com/gXCEhKaR

Комментарии:

1. Привет, пожалуйста, добавьте пример ваших данных

2. @AiratMustaev Я отредактировал свой пост, чтобы включить пример анимационных данных

Ответ №1:

Да, спасибо, я начал это дома, но у вас есть значения ширины и высоты, установленные для компонента Лотти. Если вы хотите, чтобы Лотти меняла свой размер в зависимости от размера экрана, вам нужно добавить крючок для изменения экрана.

Изменение размера крючка

   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
}
 

Ваш компонент

 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>
  )
}