Задержка итераций в цикле for, который содержит операторы if / else

#javascript #jquery #animation #gsap

#javascript #jquery #Анимация #gsap

Вопрос:

Я пытаюсь создать игру Simon Says. У меня есть функция, которая выполняет итерации по массиву чисел. Каждое число связано с действием (поэтому соответствующая анимация кнопки). Это отлично работает, когда последовательность имеет длину всего 1 значение, но тогда все они просто воспроизводятся одновременно. Я искал способы установить задержку между итерациями, но ничего не нашел для циклов for, которые содержат операторы if / else .

Я попробовал решение, которое нашел здесь:

 function show_sequence() {
    var k = right_seq.length;

    //assign each button a number
    //when the loop goes over it that button's animation plays
    (function animation(i) {
            setTimeout(function() {
            if (i == 1) { 
                setTimeout(function() {
                    TweenMax.from("#pink", 0.6, {opacity:0.3, scale:0.8, ease:Elastic.easeOut});
                    one.play();
                }, 1000);
            } else if (i == 2) {
                setTimeout(function() {
                    TweenMax.from("#blue", 0.6, {opacity:0.3, scale:0.8, ease:Elastic.easeOut});
                    two.play();
                }, 1000);
            } else if (i == 3) {
                setTimeout(function() {
                    TweenMax.from("#yellow", 0.6, {opacity:0.3, scale:0.8, ease:Elastic.easeOut});
                    three.play();
                }, 1000);
            } else {
                setTimeout(function() {
                    TweenMax.from("#green", 0.6, {opacity:0.3, scale:0.8, ease:Elastic.easeOut});
                    four.play();
                }, 1000);
            }; //end for loop
            if (--i) {
                animation(i);
            }
        }, 200);
})(k);
}
  

И это работает в том смысле, что добавляет задержку между анимацией и звуком, но не воспроизводит их в правильном порядке. Например, если массив равен [3, 4, 1, 2], анимация размещается не на этих кнопках, а в порядке [4, 3, 2, 1], и он не работает более 4 раундов.

Вот скрипка, но игра не закончена, поэтому я не знаю, поможет ли это. Нажмите на маленький зеленый кружок, чтобы начать / продолжить добавление раундов.

Комментарии:

1. Лучшим подходом может быть использование animate() и complete обратный вызов.

Ответ №1:

Вместо того, чтобы использовать все эти таймеры, используйте метод staggerFrom , который сделает задержку за вас. Чтобы получить серию producesd из right_seq массива, преобразуйте этот массив в список имен элементов:

 function show_sequence() {
    var k = right_seq.length;
    var circles = right_seq.map(function (num) {
        return ['#pink','#blue','#yellow','#green'][num-1];
    });
    // this will apply the animation in sequence
    TweenMax.staggerFrom(circles, 0.6, {opacity:0.3, scale:0.8, ease:Elastic.easeOut}, 0.6);
}
  

Теперь, когда у вас есть это, вам может потребоваться просмотреть саму анимацию, потому что этот метод немедленно вернет всем затронутым элементам их первоначальный стиль, но выполнит анимацию с «поэтапной» задержкой.

Если это не сработает, реализуйте свой цикл, используя onComplete свойство:

 function show_sequence() {
    var circles = right_seq.map(function (num) {
        return ['#pink','#blue','#yellow','#green'][num-1];
    });
    (function loop(i) {
        if (i>=circles.length) return;
        TweenMax.from(circles[i], 0.6, {
            opacity:0.3, scale:0.8, ease:Elastic.easeOut, 
            onComplete: loop.bind(this,i 1)
        });
    })(0);
}
  

Комментарии:

1. Спасибо, это выглядит намного чище, я попробую

2. Я добавил второй вариант, если первое решение не подходит для вас с точки зрения стиля CSS.

Ответ №2:

Это быстрое решение. Есть ряд вещей, которые вы могли бы сделать, чтобы улучшить его, но это должно помочь вам преодолеть текущее препятствие.

Проблема заключалась в том, что вы вообще не использовали свою последовательность. Число, которое вы передавали в show_sequence, было просто длиной массива, который вы уменьшали (отсюда и пришли 4, 3, 2, 1). На самом деле вы никогда не получали индекс кнопки из своего массива последовательностей

 function show_sequence() {
  var k = right_seq.length;

  //assign each button a number
  //when the loop goes over it that button's animation plays
  (function animation(i) {
    if (i >= right_seq.length) {
      return;
    }
    setTimeout(function() {
      if (right_seq[i] == 1) {
        setTimeout(function() {
          TweenMax.from("#pink", 0.6, {
            opacity: 0.3,
            scale: 0.8,
            ease: Elastic.easeOut
          });
          one.play();
        }, 1000);
      } else if (right_seq[i] == 2) {
        setTimeout(function() {
          TweenMax.from("#blue", 0.6, {
            opacity: 0.3,
            scale: 0.8,
            ease: Elastic.easeOut
          });
          two.play();
        }, 1000);
      } else if (right_seq[i] == 3) {
        setTimeout(function() {
          TweenMax.from("#yellow", 0.6, {
            opacity: 0.3,
            scale: 0.8,
            ease: Elastic.easeOut
          });
          three.play();
        }, 1000);
      } else {
        setTimeout(function() {
          TweenMax.from("#green", 0.6, {
            opacity: 0.3,
            scale: 0.8,
            ease: Elastic.easeOut
          });
          four.play();
        }, 1000);
      }; //end for loop
      animation(  i);
    }, 200);
  })(0);
}
  

Комментарии:

1. @l-emi Вы должны проверить ответ @trincot. Вероятно, это близко к тому, куда вы хотите двигаться. Тем более, что вы могли бы свернуть большую часть функции show_sequence, чтобы использовать массив, который просто содержал такие вещи: [ { button: 'pink', sound: one }, { button: 'blue', sound: two } ... ] вместо if (i == 1) .. if (i == 2) .. структуры