你如何在反应中取消和重置css动画?

Posted

技术标签:

【中文标题】你如何在反应中取消和重置css动画?【英文标题】:How do you cancel and reset css animations in react? 【发布时间】:2017-01-06 04:57:15 【问题描述】:

我想做什么

我有一个精灵表,我将它用于一些简单的动画。我有一个有两个动画的“播放器”。一种用于攻击,一种用于站立。当前行为如下:“stand”是默认动画。当玩家被点击时,播放“攻击”动画并切换回“站立”。

对于玩家在攻击时被点击的特殊情况,我希望动画“攻击”动画重置。

我的代码

// React Component
class Player extends React.Component 
  constructor(props) 
    super(props);
    this.state = 
      timeout: null
    ;
  

  attack(e) 
    if (this.state.timeout)  clearTimeout(this.state.timeout);  
    var $el = $(e.target);
    $el.css(
      backgroundPosition: '0 220px',
      animationName: 'attack',
      width: '300px'
    );
    this.state.timeout = setTimeout(function() 
      $el.css(
        backgroundPosition: 'left top',
        animationName: 'stand',
        width: '250px'
      );
    , 2000);
  

  render () 
    return (
      <div onClick=this.attack.bind(this) className="player main">this.props.name</div>
    );
  



     /* The css */
     .player 
        width: 250px;
        height: 220px;
        background: url('assets/player.png') left top;
        animation: stand 1.2s steps(3) infinite;
        animation-direction: alternate;
      
      @keyframes stand 
        100%  
          background-position: -750px 0; 
        
      
      @keyframes attack 
        100%  
          background-position: -900px 220px; 
        
      

我想做什么

我知道,既然我设置了“站立”动画,我将不得不取消它并制作一个新的 setTimeout 来跟随“站立”动画。但是,它看起来仍然有点时髦。我尝试使用 forceUpdate() 来查看是否可以重新渲染并重置所有内容,然后启动“攻击”动画,但它似乎没有做任何事情。

我有另一个想法,使用 jquery 删除和重新附加 dom 元素,但我觉得它会变得混乱,我相信我可能以错误的方式处理这个问题。大家有什么想法吗?

【问题讨论】:

【参考方案1】:

对于复杂的动画,可以使用https://github.com/chenglou/react-motion,可以借鉴https://egghead.io/playlists/react-react-animation-using-react-motion和https://egghead.io/lessons/react-react-motion-introduction-to-the-spring-component

对于简单的,我宁愿从元素中添加和删除类以启用动画并重置它。

如果我理解正确,您在 react 中使用 jQuery。好吧,要更新 CSS,你不应该在 react 中使用它。

在 react 中使用 jQuery 应该有更充分的理由,因为在 react 中更新内联 css 非常简单。

以下是我尝试做的方式:

// React Component
class Player extends React.Component 
    constructor(props) 
      super(props);
      this.state = 
        direction: null,
        timeout: null
      ;
    

    attack(e) 

      //following line can be used to identify multiple targets
      //let target = (e.target);
      if (this.state.timeout !== null) 
        window.clearTimeout(this.state.timeout)
      
      let timeout = setTimeout(() => 
        this.setState(
          direction: null,
          timeout: null
        );
      , 8000)
      let direction = null;
      if (e.ctrlKey) 
        direction = 'anticlockwise'
       else 
        direction = 'clockwise'
      
      if (this.state.direction !== direction) 
        this.setState(
          direction, timeout
        );
      

    

    render() 
        let classNames = ["player", "main"];
        let styles = 
        if (this.state.direction !== null) 
          if (this.state.direction === 'clockwise')
            styles.zoom = 0.8
          else
            styles.zoom = 1.2
          classNames.push(this.state.direction)
        
        return ( < div onClick = 
            this.attack.bind(this)
          
          style=styles
          className = 
            classNames.join(' ')
           > 
            this.props.name
           < /div>
    );
  

ReactDOM.render(<Player / > , document.getElementById('game'));
.player 
  width: 100px;
  height: 100px;
  margin: 50px;
  zoom: 1;
  transition: all linear 0.3s;
  display: inline-block;
  background-color: #ccc;
  animation-timing-function: linear;

.clockwise 
  animation: clockwise 5s infinite;

.anticlockwise 
  animation: anticlockwise 5s infinite;

@keyframes clockwise 
  0% 
    transform: rotate(0deg)
  
  50% 
    transform: rotate(180deg)
  
  100% 
    transform: rotate(360deg)
  

@keyframes anticlockwise 
  0% 
    transform: rotate(360deg)
  
  50% 
    transform: rotate(180deg)
  
  100% 
    transform: rotate(0deg)
  
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="game"></div>

【讨论】:

哦,谢谢!看起来很简单;我希望我能想到这一点。我还没有测试过,但我相信这会奏效。如果我认真对待动画,我会确保查看这些资源 在上面的例子中,按 ctrl+click 进行逆时针旋转。非常感谢您的支持。 我会在获得 15 个代表后尝试投票。当我 ctrl + 单击时,该示例似乎对我不起作用。它适用于运行 chrome 的 mac 浏览器吗?此外,添加和删除类不会重置动画。这就是为什么我考虑使用 jquery 将其删除并添加回 dom 的原因。这里有一个例子css-tricks.com/restart-css-animation 我在windows机器上写了答案;虽然只需单击框进行顺时针旋转。 在同一页面中,css-tricks.com/restart-css-animation/#article-header-id-0 他们建议通过void element.offsetWidth 进行回流,其余与添加和删除类相同。这个relow也可以在上面的代码中使用void e.target.offsetWidth

以上是关于你如何在反应中取消和重置css动画?的主要内容,如果未能解决你的问题,请参考以下文章

如何实现反应本土艺术的动画

如何取消在颤动中打开和关闭导航抽屉的动画?

如何在不将页面滚动条重置为顶部的情况下使用 jQuery 为固定 div 设置动画

如何正确重置 Vue Composition Api 反应值

css3 动画 如何让元素走一条曲线(例如:4分之一圆)

如何停止CSS3的动画