【问题标题】:How do you cancel and reset css animations in react?你如何在反应中取消和重置css动画?
【发布时间】: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 元素,但我觉得它会变得混乱,我相信我可能以错误的方式处理这个问题。大家有什么想法吗?

【问题讨论】:

    标签: javascript css animation reactjs


    【解决方案1】:

    对于复杂的动画,可以使用https://github.com/chenglou/react-motion,可以借鉴https://egghead.io/playlists/react-react-animation-using-react-motionhttps://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
    猜你喜欢
    • 2021-03-30
    • 2011-12-01
    • 2018-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-26
    • 1970-01-01
    • 2021-12-11
    相关资源
    最近更新 更多