Как анимировать высоту элемента в React с ReactCSSTransitionGroup?

Я пытаюсь анимировать высоту элемента с помощью ReactCSSTransitionGroup, так что я хочу, чтобы анимация выглядела так:

http://jsfiddle.net/cherrry/hgk4Lme9/

Проблема в том, что я не всегда знаю высоту элемента, поэтому я попытался взломать scrollHeight, clientHeight или что-то подобное во время componentDidMount и попытаться установить node.style.height или добавить правила в таблицу стилей

http://jsfiddle.net/cherrry/dz8uod7u/

Оставшаяся анимация выглядит неплохо, однако, когда элемент входит, она немного мигает, а анимация масштабирования выглядит странно.

Должно быть, из-за того, что запрос node.scrollHeight вызвал немедленный рендеринг, так или иначе, чтобы получить ту же информацию и ввести правила css до начала анимации? Или я должен думать иначе?

Я не очень доволен решением max-height, так как полученная скорость анимации будет очень странной, если max-height не приближается или меньше к height, а высота моих компонентов сильно варьируется.

Я мог представить, что окончательное решение может быть немного грязным, но я думаю, что создание его в Mixin будет достаточно хорошим, чтобы повторно использовать его в любом месте

Ответы

Ответ 1

У меня была такая же проблема, и в итоге я написал автономный компонент для анимации высоты.

Здесь вы можете увидеть демо: https://stanko.github.io/react-animate-height/

Это намного проще в использовании, а целая библиотека действительно маленькая (~ 200 строк)

<AnimateHeight
  duration={ 500 }
  height={ 'auto' }
>
  <h1>Your content goes here</h1>
  <p>Put as many React or HTML components here.</p>
</AnimateHeight>

Извините за бесстыдное саморекламу, но я думаю, что это может сэкономить вам много времени, если у вас есть более одного компонента для анимации.

Ура!

Ответ 2

После немного большего эксперимента я придумал решение, используя низкоуровневый API ReactTransitionGroup вместо высокоуровневого ReactCSSTransitionGroup

Здесь JSFiddle с рабочим решением: http://jsfiddle.net/cherrry/0wgp34cr/

Перед анимацией он делает 3 вещи:

  • получить вычисленную высоту, paddings и поля
  • скрыть элемент display: none и добавить .anim-enter, чтобы установить высоту в 0
  • создать правило css для .anim-enter-active

Чтобы запустить анимацию, она делает 2 вещи:

  • показать элемент
  • добавить .anim-enter-active для запуска анимации

Некоторые номера и имя класса в JSFiddle были жестко закодированы, но должно быть достаточно легко преобразовать "mixin" в класс React в качестве замены ReactCSSTransitionGroup