Итерация массива с анимацией и условиями - PullRequest
2 голосов
/ 18 июня 2019

Я хочу перебрать (используя setIterval) массив строк:

const colors = ['all', 'red', 'blue', 'green', 'yellow']

Результат:

console.log('all') 
console.log('red')    // after 20 sec
console.log('blue')   // after 10 sec
console.log('green')  // after 10 sec
console.log('yellow') // after 10 sec

Но я должен учитывать и случайное число: во время итерации я могу или не хочу показывать этот цвет (это относится к одному цвету (red, blue, green, yellow ) не all). Это зависит от определенного условия, что мы можем рассмотреть случайное число в этом упрощенном примере:

if(Math.random() >= 0.5)
    showTheColor
else
    doesntShowTheColor

Я моделирую пример:

start animation
  show color all for 20 seconds

coin throw for color red = 0.7
  show color red for 10 seconds

coin throw for color blue = 0.4
  /

coin throw for color green = 0.1
  /

coin throw for color yellow = 0.8
  show color yellow for 10 seconds

show color all for 20 seconds

coin throw for color red = 0.2
  /

coin throw for color blue = 0.3
  /

coin throw for color green = 0.78
  show color green for 10 seconds

coin throw for color yellow = 0.5
  show color yellow for 10 seconds

show color all for 20 seconds

coin throw for color red = 0.6
  show color red for 10 seconds

coin throw for color blue = 0.7
  show color blue for 10 seconds

coin throw for color green = 0.4
  /

coin throw for color yellow = 0.1
  /

show color all for 20 seconds

coin throw for color red = 0.2
  /

coin throw for color blue = 0.1
  /

coin throw for color green = 0.3
  /

coin throw for color yellow = 0.15
  /

// NB: doesn't show color all for 20 seconds because all the previous colors are null. If I showed all for 20 sec, I would have a total of 40 sec of all and that's not what I want
coin throw for color red = 0.5 
  show color red for 10 seconds

Вот кусок моего кода:

const INTERVAL_ALL = 20 // sec
const INTERVAL_SINGLE = 10 // sec

export class Animation extends React.Component {
  interval = null
  i = -1
  colors: string[]

  async componentDidMount() {
    this.colors = ['all', 'red', 'blue', 'green', 'yellow']
    this.startPlaying()
  }

  startPlaying = () => {
    this.interval = window.setInterval(() => this.updateColor(), INTERVAL * 1000) // which interval?
  }

  // where do I put conditions and how?
  updateColor() {
    this.i = this.i === this.colors.length - 1 ? 0 : this.i + 1
    const color = this.colors[this.i]
    this.doSomethingWithColor(color)
  }

  componentWillUnmount() {
    clearInterval(this.interval)
  }

  doSomethingWithColor(color) {
    console.log(color)
  }

  render() {
    return (...)
  }
}

Код является упрощенной версией, он не учитывает различные типы времени и условий. Мне нужна помощь

Большое спасибо

Ответы [ 2 ]

1 голос
/ 18 июня 2019

возможно, вы ищете что-то вроде этого:

Сохраняя это относительно просто, вот и песочница: https://codesandbox.io/s/gallant-bardeen-7rxmh

class App extends React.Component {
  state = {
    colors: ["red", "orange", "yellow", "green", "blue"],
    currentColor: "red",
    currentIndex: 0,
    colorWasSkipped: false
  };

  componentDidMount() {
    this.changeColor();
  }

  componentDidUpdate() {
    const { currentIndex, colorWasSkipped } = this.state;

    setTimeout(
      () => {
        this.changeColor();
      },
      currentIndex === 0 && !colorWasSkipped
        ? "20000"
        : colorWasSkipped
        ? 0
        : "10000"
    );
  }

  changeColor = () => {
    const { colors, currentIndex } = this.state;
    const randomNumber = Math.random();

    const newColor =
      currentIndex < colors.length - 1 ? colors[currentIndex + 1] : colors[0];

    const newIndex = currentIndex < colors.length - 1 ? currentIndex + 1 : 0;

    if (randomNumber >= 0.5) {
      console.log(randomNumber + " changed " + newColor);
      this.setState({
        currentColor: newColor,
        currentIndex: newIndex,
        colorWasSkipped: false
      });
    } else {
      console.log(randomNumber + " skip " + newColor);
      this.setState({
        currentIndex: newIndex,
        colorWasSkipped: true
      });
    }
  };

  render() {
    const color = this.state.currentColor;
    return <div style={{ height: "200px", background: `${color}` }} />;
  }
}

Дайте мне знать, если у вас есть какие-либо вопросы,Если цвет пропущен, мы немедленно пробуем новый цвет, и если его случайное число меньше 0,5, мы также пропускаем его.Цикл продолжается до тех пор, пока мы не получим число, большее или равное 0,5, затем мы отобразим этот цвет в течение 10 секунд, если только мы не вернемся к индексу 0, а вместо этого отобразим этот цвет в течение 20 секунд.

0 голосов
/ 18 июня 2019

Я сам не React, но дай мне знать, если это то, что ты ищешь. Кроме того, вы не упомянули, каким должно быть поведение, если после подбрасывания монеты ничего не должно произойти - следует ли нам сразу же подбрасывать монету или нам все еще ждать интервала?

const INTERVAL_ALL = 20 // sec
const INTERVAL_SINGLE = 10 // sec

export class Animation extends React.Component {
  // interval = null - not needed, timeout will do
  activeInterval: number;
  i = 1 // should start at index 1, right after 'all'
  colors: string[]
  currentColor: string;

  async componentDidMount() {
    this.colors = ['all', 'red', 'blue', 'green', 'yellow']
    this.currentColor = this.colors[0] // set current color to 'all' at beginning
    this.activeInterval = INTERVAL_ALL; // animation starts with all, so 20 secs.
    this.startPlaying();
  }

  startPlaying = () => {
    setTimeout(() => {
      this.attemptColorChange();
    }, this.activeInterval * 1000) //
  }

  // where do I put conditions and how?
  pickNewColor(): string {
    this.i = this.i % this.colors.length
    const newColor = this.colors[this.i++]
    return newColor;
  }

  componentWillUnmount() {
    // clearInterval(this.interval)
  }

  attemptColorChange() {
    const newColor = this.pickNewColor();
    const shouldChangeColor = Math.random() >= 0.5
    if (shouldChangeColor) {
      if (newColor === 'all') {
        this.activeInterval = INTERVAL_ALL;
      } else {
        this.activeInterval = INTERVAL_SINGLE;
      }
      this.currentColor = newColor;
      this.startPlaying();
    }
    else {
      this.attemptColorChange();
    }
  }

  render() {

  }
}
...