TransitionGroup / CSSTransition с положением: относительный? - PullRequest
0 голосов
/ 14 февраля 2019

Я занимаюсь разработкой виджета React (пошаговый мастер), который извлекает и показывает контент из API.Я не знаю, сколько времени занимают тексты, которые я получаю из API.Так что я не знаю, высота виджета.Виджет должен увеличивать высоту относительно содержимого (как HTML-элементы по умолчанию).Не должно быть прокрутки.

Я не могу установить фиксированную высоту здесь.Поэтому я не могу установить position: absolute на слайды, которые я хочу анимировать.

На данный момент анимация выглядит следующим образом:

Второй слайд появляется под первым слайдом до первого слайдаисчезает, а второй движется вверх.Конечно, это совершенно безобразно.

Если я установлю фиксированную высоту и абсолютную позицию для слайдов, все будет работать нормально и плавно.

Вы можете увидеть демонстрацию моей проблемы здесь.: https://codepen.io/anon/pen/jdQPRw

1 Ответ

0 голосов
/ 19 февраля 2019

TransitionGroup должен быть оберткой для нескольких Transition или CSSTransition. Итак, сначала вы должны обернуть каждый слайд в CSSTransition.Второе свойство let in для обработки «hide & show» для компонента

<CSSTransition in={slide === 2}

Затем используйте свойство unmountOnExit для размонтирования слайда после завершения анимации

Я разветвил вашу ручкуи отредактируйте его, и оно работает, пожалуйста, проверьте изменения https://codepen.io/anon/pen/yZZqKo

const { TransitionGroup, CSSTransition } = ReactTransitionGroup;

class Slide extends React.Component {
  render() {
    return <div 
               className="slide"
             style={{backgroundColor: this.props.bg}}
             >{this.props.content}</div>
  } 
}

const content1 = 'Demo Text with different Length. This will get fetched from API. Demo Text with different Length. This will get fetched from API. Demo Text with different Length. This will get fetched from API. ';
const content2 = 'Demo Text with different Length. This will get fetched from API. Demo Text with different Length. This will get fetched from API. Demo Text with different Length. This will get fetched from API. Demo Text with different Length. This will get fetched from API. Demo Text with different Length. This will get fetched from API. Demo Text with different Length. This will get fetched from API. Demo Text with different Length. This will get fetched from API. Demo Text with different Length. This will get fetched from API. Demo Text with different Length. This will get fetched from API. ';

class Widget extends React.Component {

  state = { slide: 1 }

  render() {
    const slide = this.state.slide;
    return (
      <div className="widget">
          <TransitionGroup className="wrapper"><div>
            <CSSTransition
              in={slide === 1}
              classNames="fade"
              timeout={{ enter: 500, exit: 0 }}
              appear
              unmountOnExit
              ><Slide content={ content1 } bg="#fafafa" />
            </CSSTransition></div><div>
            <CSSTransition
              in={slide === 2}
              classNames="fade"
              timeout={{ enter: 500, exit: 0 }}
              appear
              unmountOnExit
              ><Slide content={ content2 } bg="#ccc" />
            </CSSTransition></div>
          </TransitionGroup>
          <div className="buttons">
            <button 
              className="next" 
              onClick={ () => this.setState({slide: 1})}
              >Slide 1</button>
            <button 
              className="next" 
              onClick={ () => this.setState({slide: 2})}
              >Slide 2</button>
          </div>
      </div>
    );
  }
} 


ReactDOM.render(
  <Widget />,
  document.getElementById('root')
);
body {
  background: #eee;
}

.page {
  max-width: 500px;
  margin: 30px auto;
}

.widget {
  padding: 20px;
  background: #fff;
  border-radius: 5px;
  overflow: hidden;
}

.slide {
  padding: 20px;
  border-radius: 3px;
}

.buttons {
  display: flex;
}

.next {
  display: flex;
  flex: 1;
  margin: 10px;
  background: blue;
  color: #fff;
  padding: 14px;
  margin-top: 10px;
  border: 0;
  border-radius: 3px;
  font-size: 20px;
  text-decoration: none;
  text-align: center;
}

.fade-enter {
  opacity: 0.01;
}
.fade-enter-active {
  opacity: 1;
  transition: opacity 500ms ease-in;
}
.fade-enter-done {opacity:1}
.fade-exit {
  opacity: 1;
}
.fade-exit-active {
  opacity: 0.01;
  transition: opacity 500ms ease-in;
}
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-transition-group/2.5.3/react-transition-group.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-router-dom/4.3.1/react-router-dom.js"></script>
<div class="page">
  <h1>Content</h1>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ullamcorper ac tortor quis vulputate. Cras commodo dolor quis odio rutrum accumsan. Vestibulum aliquam bibendum odio vel auctor. In feugiat elit ac accumsan posuere. Donec facilisis tellus vitae faucibus pharetra. Aenean arcu dolor, molestie ut cursus vitae, congue id tortor. In scelerisque scelerisque dolor eget laoreet. Donec et consequat quam. Maecenas suscipit quis mi ac luctus. Aliquam aliquet vitae erat ut ultricies. Suspendisse laoreet lacinia nisl sit amet facilisis. Aliquam ac lorem leo. Etiam feugiat sagittis erat eget ullamcorper. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>

<div id="root">
    <!-- This element's contents will be replaced with your component. -->
</div>
  
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ullamcorper ac tortor quis vulputate. Cras commodo dolor quis odio rutrum accumsan. Vestibulum aliquam bibendum odio vel auctor. In feugiat elit ac accumsan posuere. Donec facilisis tellus vitae faucibus pharetra. Aenean arcu dolor, molestie ut cursus vitae, congue id tortor. In scelerisque scelerisque dolor eget laoreet. Donec et consequat quam. Maecenas suscipit quis mi ac luctus. Aliquam aliquet vitae erat ut ultricies. Suspendisse laoreet lacinia nisl sit amet facilisis. Aliquam ac lorem leo. Etiam feugiat sagittis erat eget ullamcorper. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
...