最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How do you cancel and reset css animations in react? - Stack Overflow

programmeradmin5浏览0评论

What I am trying to do

I have a sprite sheet and I am using it for some simple animations. I have a "player" that has two animations. One for attacking and one for standing. The current behavior is as follows: "stand" is the default animation. When the player is clicked, the "attack" animation is played and switched back to "stand."

For the special case that the player is clicked while attacking, I want the animation "attack" animation to reset.

My code

// 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; 
        }
      }

What I tried to do

I knew that since I setTimeout the "stand" animation, I would have to cancel it and make a new setTimeout to go after the "stand" animation. However, it still looks a bit funky. I tried to use forceUpdate() to see if I could just rerender and reset everything and then start the "attack" animation, but it doesn't seem to do anything.

I have another idea using jquery to remove and reattach the dom element but I feel like it would get messy and I believe I might be approaching this problem the wrong way. Do you guys have any ideas?

What I am trying to do

I have a sprite sheet and I am using it for some simple animations. I have a "player" that has two animations. One for attacking and one for standing. The current behavior is as follows: "stand" is the default animation. When the player is clicked, the "attack" animation is played and switched back to "stand."

For the special case that the player is clicked while attacking, I want the animation "attack" animation to reset.

My code

// 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; 
        }
      }

What I tried to do

I knew that since I setTimeout the "stand" animation, I would have to cancel it and make a new setTimeout to go after the "stand" animation. However, it still looks a bit funky. I tried to use forceUpdate() to see if I could just rerender and reset everything and then start the "attack" animation, but it doesn't seem to do anything.

I have another idea using jquery to remove and reattach the dom element but I feel like it would get messy and I believe I might be approaching this problem the wrong way. Do you guys have any ideas?

Share Improve this question asked Aug 30, 2016 at 3:49 inspiredtoliveinspiredtolive 1712 gold badges3 silver badges7 bronze badges 0
Add a ment  | 

1 Answer 1

Reset to default 3

For plex animations, you can use https://github./chenglou/react-motion which can learnt from https://egghead.io/playlists/react-react-animation-using-react-motion and https://egghead.io/lessons/react-react-motion-introduction-to-the-spring-ponent

For simple ones, I would rather add and remove classes from element to enable the animation and reset it.

And if I am understanding it correctly, you are using jQuery inside react. Well to update the CSS, you should not use it inside react.

There should be more strong reasoning to use jQuery in react because updating inline css is very simple in react.

Following is the way I would attempt to do it:

// 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./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="game"></div>

发布评论

评论列表(0)

  1. 暂无评论