react-transition-group 动画的布局中断

Posted

技术标签:

【中文标题】react-transition-group 动画的布局中断【英文标题】:Layout breaks on react-transition-group animation 【发布时间】:2019-03-20 09:03:52 【问题描述】:

我正在尝试熟悉react-transition-group,但遇到了一些问题。在一个简单的组件中,它显示当前计数器并在incrementdecrement 上为显示的值设置动画,当输入新值时,它会移动前一个值,从而产生突然的效果。这可能是因为具有不透明度0 的新元素进入圆顶并且两个值同时显示。

整个组件如下所示:

import React,  Component  from "react";
import  TransitionGroup, CSSTransition  from "react-transition-group";

import "./App.css";

class App extends Component 
  state = 
    progress: 0
  ;
  incr = () => 
    this.setState(
      progress: this.state.progress + 1
    );
  ;
  decr = () => 
    this.setState(
      progress: this.state.progress - 1
    );
  ;
  render() 
    return (
      <div className="App">
        <TransitionGroup>
          <CSSTransition
            in=true
            appear=true
            key=this.state.progress
            timeout=2000
            classNames="slide"
          >
            <div key=this.state.progress>this.state.progress</div>
          </CSSTransition>
        </TransitionGroup>
        <button onClick=this.decr>decr</button>
        <button onClick=this.incr>incr</button>
      </div>
    );
  


export default App;

过渡类如下所示:

/* slide enter */
.slide-enter 
  opacity: 0;
  transform: scale(0.97) translateX(5px);
  z-index: 1;

.slide-enter.slide-enter-active 
  opacity: 1;
  transform: scale(1) translateX(0);
  transition: opacity 3000ms linear 1000ms, transform 3000ms ease-in-out 1000ms;


/* slide exit */
.slide-exit 
  opacity: 1;
  transform: scale(1) translateX(0);

.slide-exit.slide-exit-active 
  opacity: 0;
  transform: scale(0.97) translateX(5px);
  transition: opacity 1500ms linear, transform 1500ms ease-out;

.slide-exit-done 
  opacity: 0;

我想实现以下行为:在递增/递减时,当前显示的计数器逐渐消失,而新的计数器在当前计数器不存在后淡入。

【问题讨论】:

【参考方案1】:

这可能是因为不透明度为 0 的新元素进入圆顶,并且两个值同时显示。

是的,就是这样。您可以使用 position: absolute 从文档流中删除元素,并且您可能还需要以某种方式补偿从文档流中删除这些元素的事实。

<TransitionGroup>
  <CSSTransition
    in=true
    appear=true
    key=this.state.progress
    timeout=2000
    classNames="slide"
  >
    <div className="animating" key=this.state.progress>
      this.state.progress
    </div>
  </CSSTransition>
</TransitionGroup>

CSS

.animating 
  position: absolute;


button:first-of-type 
  margin-top: 50px;

没有 React 过渡组

JS

import React,  Component  from "react";
import "./App.css";

class App extends Component 
  state = 
    progress: 0,
    transition: "entering" /* entering | exiting */
  ;
  instanceVariables = 
    temporaryProgress: 0,
    timeoutId: null
  ;
  animate = () => 
    clearTimeout(this.instanceVariables.timeoutId);
    this.instanceVariables.timeoutId = setTimeout(() => 
      this.setState(
        progress: this.instanceVariables.temporaryProgress,
        transition: "entering"
      );
    , 1000);
    this.setState(
      transition: "exiting"
    );
  ;
  incr = () => 
    this.instanceVariables.temporaryProgress += 1;
    this.animate();
  ;
  decr = () => 
    this.instanceVariables.temporaryProgress -= 1;
    this.animate();
  ;
  render() 
    return (
      <div className="App">
        <div className=`animate $this.state.transition`>
          this.state.progress
        </div>
        <button onClick=this.decr>decr</button>
        <button onClick=this.incr>incr</button>
      </div>
    );
  


export default App;

CSS

.animate 
  transition: opacity 1s linear, transform 1s ease-in-out;


.animate.exiting 
  transform: translateX(20px);
  opacity: 0;


.animate.entering 
  transform: translateX(0);
  opacity: 1;

【讨论】:

感谢您的回答!但是有没有办法延迟退出动画,所以它会在新动画进入之前退出?在更复杂的布局中,我认为将absolute 赋予元素会破坏很多东西。谢谢! position: absolute 正是我为 my app shell layout 所做的(它使用 React Transition Group 进行路由转换)。如果你只希望一次出现一个元素,那么最好不要使用 React Transition Group,因为你真的不需要它。你可以使用普通的 React。 如果我只想将退出元素的不透明度从 1 设置为 0,反之亦然以进入元素,我将如何实现这一点?我现在正在与布局作斗争,以使我想要过渡的元素成为绝对的,但到目前为止它还不起作用,所以任何关于我如何在没有过渡组的情况下做到这一点的建议都非常受欢迎!再次感谢,这意味着很多 @DimitryIvashchuk 当然,我已经更新了我的答案以包含一个示例。 感谢您的帮助和建议,我会根据他们的努力使其工作!

以上是关于react-transition-group 动画的布局中断的主要内容,如果未能解决你的问题,请参考以下文章

react-transition-group动画以及数字滚动效果实现

使用react-transition-group实现动画

使用 ReactDOM createPortal 为 react-transition-group 设置动画

如何使用 React-Transition-Group 显示和隐藏带有动画的模态/对话框?

如何让“react-beautiful-dnd”不触发“react-transition-group”动画?

在组件中加载初始数据时,如何在 react-transition-group 中暂停动画?