【问题标题】:Blink elements in sequence按顺序闪烁元素
【发布时间】:2018-09-26 22:44:47
【问题描述】:

大家好,所以我正在做这件事,我有 4 个方块,当我单击按钮时,3 个随机方块必须按顺序以不同的颜色闪烁。我需要将闪烁的方块的 id 存储在一个数组中。我想不通的是如何让他们一个接一个地眨眼。这就是我目前所拥有的...https://codepen.io/anon/pen/dmBxYe?editors=0110

class App extends React.Component {
constructor() {
    super();

    this.state = {
        colors: ['yellow', 'red', 'blue', 'green'],
        quantity: 3,
    }
}
start() {
    const {quantity} = this.state;
    const quantityArray = Array.from(Array(quantity));
    const pieces = Array.from(document.querySelectorAll('.game-piece')); 

    quantityArray.forEach((item, i) => {
      setTimeout(() => {    
        pieces[i].classList.toggle(`${this.state.colors[i]}`);
      }, i * 500); // we're passing x
      setTimeout(() => {
        pieces[i].classList.toggle(`${this.state.colors[i]}`);
      }, 700 * (i))
    });
}
render() {
    return (
        <div className="memory-game">
            {this.state.colors.map((gamePiece, i) => {
                return <div key={`gamePiece-${i}`} className="game-piece"></div>
            })}

            <button onClick={this.start.bind(this)} className="start-game">Start the game</button>
        </div>
    )
}
}

React.render(<App />, document.getElementById('app'));

【问题讨论】:

  • 如果要一个接一个的发起,最后在里面先发起超时调用

标签: javascript arrays reactjs settimeout setinterval


【解决方案1】:

你可以试试这样的:

  • 创建基于递归的循环机制。
  • 接受将启动下一次调用的回调,并根据条件在循环内调用它。

Following 是一个动画函数。它添加类并在指定时间后将其删除。

如果可用,它还会调用回调。因此,调用者有责任在终止情况下不传递回调。

animate(element, className, callback) {
  setTimeout(() => {
    element.classList.toggle(className);
    setTimeout(() => {
      element.classList.toggle(className);
      if (callback) callback();
    }, 200)
  }, 500); // we're passing x
}

一个简单的基于递归的循环,如果元素和颜色存在则调用自身。您可以根据您的要求更新 if 条件。

const scheduleAnimation = (i) => {
  const element = pieces[i];
  const color = this.state.colors[i];
  if (element && color) {
    this.animate(element, color, scheduleAnimation.bind(this, ++i));
  }
}
scheduleAnimation(0);

Updated codepen

【讨论】:

  • 请注意,这更多的是说明如何做到这一点。因此,它没有解决任何特定条件,例如 我单击按钮 3 个随机方块。这是 OP 必须自己添加的部分
【解决方案2】:

这是一个有趣的问题。以下是你可以在 React setState 和 JS setTimeouts 的帮助下做的事情。

class App extends React.Component {
  constructor() {
    super();

    this.state = {
      colors: ["yellow", "red", "blue", "green"],
      quantity: 3,
      output: [],
      currentIndex: -1
    };
  }
  getRandomInt() {
    return Math.floor(Math.random() * Math.floor(4));
  }
  generateNumbers() {
    const output = [];
    while (output.length !== 3) {
      const generatedNumber = this.getRandomInt();
      if (!output.includes(generatedNumber)) {
        output.push(generatedNumber);
      }
    }

    return output;
  }

  start() {
    const output = this.generateNumbers();
    this.setState({ output: output }, () => {
      output.forEach((item, index) => {
        setTimeout(() => {
          this.setState({ currentIndex: item });
        }, index * 1000);
      });
    });
  }
  render() {
    return (
      <div className="memory-game">
        {this.state.colors.map((gamePiece, i) => {
          let customClass = "";
          if (i === this.state.currentIndex) {
            const css = this.state.colors[this.state.currentIndex]
              ? this.state.colors[this.state.currentIndex]
              : "";
            if (css) {
              customClass = `blink-${css}`;
            }
          }
          return (
            <div
              key={`gamePiece-${i}`}
              className={`game-piece ${customClass}`}
            />
          );
        })}

        <button onClick={this.start.bind(this)} className="start-game">
          Start the game
        </button>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("app"));
html,
body {
  width: 100%;
  height: 100%;
}

#app {
  width: 100%;
  height: 100%;
  display: table;
  background: lightgoldenrodyellow;
}

.memory-game {
  width: 40%;
  margin: 100px auto;
}

.game-piece {
  width: 50%;
  height: 40px;
  display: inline-block;
  border-radius: 10px;
  margin-bottom: 10px;
  background-color: lightgray;
  &:nth-child(2n + 1) {
    margin-right: 10px;
  }
}

.start-game {
  margin: 0 auto;
  background: red;
  color: white;
  border: none;
  display: block;
  padding: 10px 15px;
  border-radius: 5px;
}

@-webkit-keyframes blinker-red {
  0% {
    opacity: 0;
    background-color: red;
  }
  50%{
  opacity:1;
  }
  100%{
    opacity: 0;
  }
}

@-webkit-keyframes blinker-yellow {
 0% {
    opacity: 0;
    background-color: yellow;
  }
  50%{
  opacity:1;
  }
  100%{
    opacity: 0;
  }
}

@-webkit-keyframes blinker-green {
   0% {
    opacity: 0;
    background-color: green;
  }
  50%{
  opacity:1;
  }
  100%{
    opacity: 0;
  }
}

@-webkit-keyframes blinker-blue {
   0% {
    opacity: 0;
    background-color: blue;
  }
  50%{
  opacity:1;
  }
  100%{
    opacity: 0;
  }
}

.blink-red {
  text-decoration: blink;
  animation-name: blinker-red;
  animation-duration: 1s;
  animation-timing-function: ease-in-out;
}

.blink-green {
  text-decoration: blink;
  animation-name: blinker-green;
  animation-duration: 1s;
}

.blink-blue {
  text-decoration: blink;
  animation-name: blinker-blue;
  animation-duration: 1s;
}

.blink-yellow {
  text-decoration: blink;
  animation-name: blinker-yellow;
  animation-duration: 1s;
}

.blink-red {
  text-decoration: blink;
  animation-name: blinker-red;
  animation-duration: 1s;
}
<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="app"></div>

【讨论】:

    猜你喜欢
    • 2015-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-18
    • 1970-01-01
    • 2012-06-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多