Попытка запускать одну функцию после другой с помощью JS

Chris Gillett спросил: 13 июня 2018 в 11:44 в: javascript

У меня возникли проблемы с запуском одной функции, которая медленно отображает сообщение, ждет, а затем исчезает. Тем не менее, вы заметите, когда нажата кнопка, чтобы удалить конфетти и отобразить сообщение, конфетти не останавливается.

Я все еще изучаю Javascript, и я еще не испытывал этого. Но я собрал это вместе, чтобы получить то, что я ищу в качестве конечного результата.

То, что я хотел бы сделать, - это когда кнопка нажата, сообщение затухает, конфетти падает, исчезает сообщение и confetti перестает падать, но позволяет последнему кусочку конфетти упасть до его выключения ...

Вероятно, потому, что я еще не понимаю Javascript на этом уровне, но мне очень трудно получить JS делать то, что я хочу ...

Может ли кто-нибудь дать мне несколько указателей в моем коде, чтобы помочь мне в правильном направлении?

Спасибо !!

(function() {
  // globals
  var canvas;
  var ctx;
  var W;
  var H;
  var mp = 200; //max particles
  var particles = [];
  var angle = 0;
  var tiltAngle = 0;
  var confettiActive = false;
  var animationComplete = true;
  var deactivationTimerHandler;
  var reactivationTimerHandler;
  var animationHandler;

  // objects

  var particleColors = {
    colorOptions: ["Aqua", "Aquamarine ", "DarkViolet", "DodgerBlue", "Lime", "Yellow", "DeepPink", "SlateBlue", "AliceBlue", "Fuchsia", "PaleGreen", "SteelBlue", "SandyBrown", "Chocolate", "Crimson"],
    colorIndex: 0,
    colorIncrementer: 0,
    colorThreshold: 10,
    getColor: function() {
      if (this.colorIncrementer >= 10) {
        this.colorIncrementer = 0;
        this.colorIndex++;
        if (this.colorIndex >= this.colorOptions.length) {
          this.colorIndex = 0;
        }
      }
      this.colorIncrementer++;
      return this.colorOptions[this.colorIndex];
    }
  }

  function confettiParticle(color) {
    this.x = Math.random() * W; // x-coordinate
    this.y = (Math.random() * H) - H; //y-coordinate
    this.r = RandomFromTo(10, 30); //radius;
    this.d = (Math.random() * mp) + 10; //density;
    this.color = color;
    this.tilt = Math.floor(Math.random() * 10) - 10;
    this.tiltAngleIncremental = (Math.random() * 0.07) + .05;
    this.tiltAngle = 0;

    this.draw = function() {
      ctx.beginPath();
      ctx.lineWidth = this.r / 2;
      ctx.strokeStyle = this.color;
      ctx.moveTo(this.x + this.tilt + (this.r / 4), this.y);
      ctx.lineTo(this.x + this.tilt, this.y + this.tilt + (this.r / 4));
      return ctx.stroke();
    }
  }

  $(document).ready(function() {
    SetGlobals();
    InitializeButton();

    $(window).resize(function() {
      W = window.innerWidth;
      H = window.innerHeight;
      canvas.width = W;
      canvas.height = H;
    });

  });

  function InitializeButton() {
    $('#stopButton').click(DeactivateConfetti);
    $('#startButton').click(RestartConfetti);
  }

  function SetGlobals() {
    canvas = document.getElementById("canvas");
    ctx = canvas.getContext("2d");
    W = window.innerWidth;
    H = window.innerHeight;
    canvas.width = W;
    canvas.height = H;
  }

  function InitializeConfetti() {
    particles = [];
    animationComplete = false;
    for (var i = 0; i < mp; i++) {
      var particleColor = particleColors.getColor();
      particles.push(new confettiParticle(particleColor));
    }
    StartConfetti();
  }

  function Draw() {
    ctx.clearRect(0, 0, W, H);
    var results = [];
    for (var i = 0; i < mp; i++) {
      (function(j) {
        results.push(particles[j].draw());
      })(i);
    }
    Update();

    return results;
  }

  function RandomFromTo(from, to) {
    return Math.floor(Math.random() * (to - from + 1) + from);
  }


  function Update() {
    var remainingFlakes = 0;
    var particle;
    angle += 0.01;
    tiltAngle += 0.1;

    for (var i = 0; i < mp; i++) {
      particle = particles[i];
      if (animationComplete) return;

      if (!confettiActive && particle.y < -15) {
        particle.y = H + 100;
        continue;
      }

      stepParticle(particle, i);

      if (particle.y <= H) {
        remainingFlakes++;
      }
      CheckForReposition(particle, i);
    }

    if (remainingFlakes === 0) {
      StopConfetti();
    }
  }

  function CheckForReposition(particle, index) {
    if ((particle.x > W + 20 || particle.x < -20 || particle.y > H) && confettiActive) {
      if (index % 5 > 0 || index % 2 == 0) //66.67% of the flakes
      {
        repositionParticle(particle, Math.random() * W, -10, Math.floor(Math.random() * 10) - 10);
      } else {
        if (Math.sin(angle) > 0) {
          //Enter from the left
          repositionParticle(particle, -5, Math.random() * H, Math.floor(Math.random() * 10) - 10);
        } else {
          //Enter from the right
          repositionParticle(particle, W + 5, Math.random() * H, Math.floor(Math.random() * 10) - 10);
        }
      }
    }
  }

  function stepParticle(particle, particleIndex) {
    particle.tiltAngle += particle.tiltAngleIncremental;
    particle.y += (Math.cos(angle + particle.d) + 3 + particle.r / 2) / 2;
    particle.x += Math.sin(angle);
    particle.tilt = (Math.sin(particle.tiltAngle - (particleIndex / 3))) * 15;
  }

  function repositionParticle(particle, xCoordinate, yCoordinate, tilt) {
    particle.x = xCoordinate;
    particle.y = yCoordinate;
    particle.tilt = tilt;
  }

  function StartConfetti() {
    W = window.innerWidth;
    H = window.innerHeight;
    canvas.width = W;
    canvas.height = H;
    (function animloop() {
      if (animationComplete) return null;
      animationHandler = requestAnimFrame(animloop);
      return Draw();
    })();
  }

  function ClearTimers() {
    clearTimeout(reactivationTimerHandler);
    clearTimeout(animationHandler);
  }

  function DeactivateConfetti() {
    confettiActive = false;
    ClearTimers();
  }

  function StopConfetti() {
    animationComplete = true;
  }

  function RestartConfetti() {
    ClearTimers();
    StopConfetti();
    reactivationTimerHandler = setTimeout(function() {
      confettiActive = true;
      animationComplete = false;
      InitializeConfetti();
    }, 100);

  }


  window.requestAnimFrame = (function() {
    return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {
      return window.setTimeout(callback, 1000 / 60);
    };
  })();
})();

/* Styles go here */

html,
body,
canvas {
  height: 100%;
  width: 100%;
  margin: 0;
  background-color: #1a1a1a;
}

canvas {
  display: block;
  position: relative;
  zindex: 1;
  pointer-events: none;
}

button {
  padding: 5px 10px;
  font-size: 20px;
}

.scene {
  display: flex;
  position: relative;
  width: 100%;
  height: 100%;
  align-items: center;
  justify-content: center;
}

.scene>canvas {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.scene-content {
  position: relative;
  text-align: center;
  width: auto;
  height: auto;
  font-size: 10rem;
  font-family: Roboto;
  font-weight: 200;
  color: hsla(255, 50%, 100%, 1);
  animation: hue-shift 2s infinite linear;
}

.scene-content1 {
  position: relative;
  text-align: center;
  width: auto;
  height: auto;
  font-size: 10rem;
  font-family: Roboto;
  font-weight: 200;
  color: hsla(255, 50%, 100%, 1);
  animation: hue-shift 2s infinite linear;
}

.scene-content2 {
  position: relative;
  text-align: center;
  width: auto;
  height: auto;
  font-size: 6rem;
  font-family: Roboto;
  font-weight: 100;
  color: hsla(255, 50%, 50%, 1);
  animation: hue-shift 2s infinite linear;
}

.devices {
  margin-left: auto;
  margin-right: auto;
  text-align: center;
  color: hsla(255, 50%, 100%, 1);
  animation: hue-shift 2s infinite linear;
}

@keyframes hue-shift {
  0% {
    color: hsla(0, 80%, 80%, 1);
  }
  25% {
    color: hsla(120, 80%, 80%, 1);
  }
  75% {
    color: hsla(240, 80%, 80%, 1);
  }
  100% {
    color: hsla(360, 80%, 80%, 1);
  }
}

.buttonContainer {
  display: inline-block;
}

button {
  padding: 5px 10px;
  font-size: 20px;
}

.clicker+.circle {
  -webkit-animation: rotor 1.5s linear 0s infinite normal;
  -mox-animation: rotor 1.5s linear 0s infinite normal;
  -o-animation: rotor 1.5s linear 0s infinite normal;
  animation: rotor 1.5s linear 0s infinite normal;
}

.paused {
  -webkit-animation-play-state: paused !important;
  -moz-animation-play-state: paused !important;
  -o-animation-play-state: paused !important;
  animation-play-state: paused !important;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <link href='http://fonts.googleapis.com/css?family=Roboto:400,100,300,500,700,900' rel='stylesheet'>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
  <link href="https://unpkg.com/ionicons@4.2.0/dist/css/ionicons.min.css" rel="stylesheet">
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
  <link rel="stylesheet" href="css/style.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>

<body>
  <audio id="bubble_pop">
  <source src="mp3/pop.mp3" type="audio/mp3">
  Your browser does not support the audio element.
</audio>
  <div class="scene">
    <canvas id="canvas"></canvas>
    <div class="scene-content">
      <div class="devices">
        <i class="icon ion-ios-phone-portrait" style="font-size: 1.8em;"></i>
        <i class="icon ion-ios-watch" style="font-size: 1.6em;"></i>
      </div>
      <p class="scene-content1">Success!</p>
      <p class="scene-content2">Way to go! You can now use your device!</p>
    </div>
    <!--Hiding the message on initial page load-->
    <script type="text/javascript">
      $('.scene-content').hide();
    </script>
  </div>
  <p>
    <button id="stopButton">Stop</button>
    <button id="startButton" onclick="playAudio();">Drop it like its hot</button>
  </p>

</body>
<script>
  var pop = document.getElementById("bubble_pop");

  function playAudio() {
    pop.play();
  }

  document.getElementById('startButton').addEventListener('click', function() {
    function complete() {
      $("<div>").text(this.class).appendTo(".scene-content");
    }
    $(".scene-content").fadeIn(500).delay(2500).fadeOut(500, "linear", function() {});
  });
</script>

</html>


1 ответ

Есть решение
Viney ответил: 13 июня 2018 в 03:21

FadeOut () имеет один обратный вызов, в котором вы передаете то, что должно произойти, когда анимация завершена. Вы, должно быть, попробовали это, но причина, по которой она не работала, заключается в том, что большая часть вашего js-кода находится в self executing function , которая образует другую область видимости, поэтому вы не можете вызывать какой-либо метод внутри этой области извне. Я переместил материал внутри, теперь он работает. Не сильно изменилось, просто изменилось несколько строк; помечено знаком NEWLY ADDED

(function() {
  // globals
  var canvas;
  var ctx;
  var W;
  var H;
  var mp = 200; //max particles
  var particles = [];
  var angle = 0;
  var tiltAngle = 0;
  var confettiActive = false;
  var animationComplete = true;
  var deactivationTimerHandler;
  var reactivationTimerHandler;
  var animationHandler;

  // objects

  var particleColors = {
    colorOptions: ["Aqua", "Aquamarine ", "DarkViolet", "DodgerBlue", "Lime", "Yellow", "DeepPink", "SlateBlue", "AliceBlue", "Fuchsia", "PaleGreen", "SteelBlue", "SandyBrown", "Chocolate", "Crimson"],
    colorIndex: 0,
    colorIncrementer: 0,
    colorThreshold: 10,
    getColor: function() {
      if (this.colorIncrementer >= 10) {
        this.colorIncrementer = 0;
        this.colorIndex++;
        if (this.colorIndex >= this.colorOptions.length) {
          this.colorIndex = 0;
        }
      }
      this.colorIncrementer++;
      return this.colorOptions[this.colorIndex];
    }
  }

  function confettiParticle(color) {
    this.x = Math.random() * W; // x-coordinate
    this.y = (Math.random() * H) - H; //y-coordinate
    this.r = RandomFromTo(10, 30); //radius;
    this.d = (Math.random() * mp) + 10; //density;
    this.color = color;
    this.tilt = Math.floor(Math.random() * 10) - 10;
    this.tiltAngleIncremental = (Math.random() * 0.07) + .05;
    this.tiltAngle = 0;

    this.draw = function() {
      ctx.beginPath();
      ctx.lineWidth = this.r / 2;
      ctx.strokeStyle = this.color;
      ctx.moveTo(this.x + this.tilt + (this.r / 4), this.y);
      ctx.lineTo(this.x + this.tilt, this.y + this.tilt + (this.r / 4));
      return ctx.stroke();
    }
  }

  $(document).ready(function() {
    SetGlobals();
    InitializeButton();

    $(window).resize(function() {
      W = window.innerWidth;
      H = window.innerHeight;
      canvas.width = W;
      canvas.height = H;
    });

  });

  function InitializeButton() {
    $('#stopButton').click(DeactivateConfetti);
    $('#startButton').click(RestartConfetti);
  }

  function SetGlobals() {
    canvas = document.getElementById("canvas");
    ctx = canvas.getContext("2d");
    W = window.innerWidth;
    H = window.innerHeight;
    canvas.width = W;
    canvas.height = H;
  }

  function InitializeConfetti() {
    particles = [];
    animationComplete = false;
    for (var i = 0; i < mp; i++) {
      var particleColor = particleColors.getColor();
      particles.push(new confettiParticle(particleColor));
    }
    StartConfetti();
  }

  function Draw() {
    ctx.clearRect(0, 0, W, H);
    var results = [];
    for (var i = 0; i < mp; i++) {
      (function(j) {
        results.push(particles[j].draw());
      })(i);
    }
    Update();

    return results;
  }

  function RandomFromTo(from, to) {
    return Math.floor(Math.random() * (to - from + 1) + from);
  }


  function Update() {
    var remainingFlakes = 0;
    var particle;
    angle += 0.01;
    tiltAngle += 0.1;

    for (var i = 0; i < mp; i++) {
      particle = particles[i];
      if (animationComplete) return;

      if (!confettiActive && particle.y < -15) {
        particle.y = H + 100;
        continue;
      }

      stepParticle(particle, i);

      if (particle.y <= H) {
        remainingFlakes++;
      }
      CheckForReposition(particle, i);
    }

    if (remainingFlakes === 0) {
      StopConfetti();
    }
  }

  function CheckForReposition(particle, index) {
    if ((particle.x > W + 20 || particle.x < -20 || particle.y > H) && confettiActive) {
      if (index % 5 > 0 || index % 2 == 0) //66.67% of the flakes
      {
        repositionParticle(particle, Math.random() * W, -10, Math.floor(Math.random() * 10) - 10);
      } else {
        if (Math.sin(angle) > 0) {
          //Enter from the left
          repositionParticle(particle, -5, Math.random() * H, Math.floor(Math.random() * 10) - 10);
        } else {
          //Enter from the right
          repositionParticle(particle, W + 5, Math.random() * H, Math.floor(Math.random() * 10) - 10);
        }
      }
    }
  }

  function stepParticle(particle, particleIndex) {
    particle.tiltAngle += particle.tiltAngleIncremental;
    particle.y += (Math.cos(angle + particle.d) + 3 + particle.r / 2) / 2;
    particle.x += Math.sin(angle);
    particle.tilt = (Math.sin(particle.tiltAngle - (particleIndex / 3))) * 15;
  }

  function repositionParticle(particle, xCoordinate, yCoordinate, tilt) {
    particle.x = xCoordinate;
    particle.y = yCoordinate;
    particle.tilt = tilt;
  }

  function StartConfetti() {
    W = window.innerWidth;
    H = window.innerHeight;
    canvas.width = W;
    canvas.height = H;
    (function animloop() {
      if (animationComplete) return null;
      animationHandler = requestAnimFrame(animloop);
      return Draw();
    })();
  }

  function ClearTimers() {
    clearTimeout(reactivationTimerHandler);
    clearTimeout(animationHandler);
  }

  function DeactivateConfetti() {
    confettiActive = false;
    ClearTimers();
  }

  function StopConfetti() {
    animationComplete = true;
  }

  function RestartConfetti() {
    playAudio(); // <-- NEWLY ADDED

    ClearTimers();
    StopConfetti();
    reactivationTimerHandler = setTimeout(function() {
      confettiActive = true;
      animationComplete = false;
      InitializeConfetti();
    }, 100);

  }


  window.requestAnimFrame = (function() {
    return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {
      return window.setTimeout(callback, 1000 / 60);
    };
  })();


  /**** NEWLY ADDED ****/
  var pop = document.getElementById("bubble_pop");

  function playAudio() {
    pop.play();
  }

  document.getElementById('startButton').addEventListener('click', function() {
    function complete() {
      $("<div>").text(this.class).appendTo(".scene-content");
    }
    $(".scene-content").fadeIn(500).delay(2500).fadeOut(500, "linear", function() { DeactivateConfetti(); });
  });
  /**** *********** ****/


})();
/* Styles go here */

html,
body,
canvas {
  height: 100%;
  width: 100%;
  margin: 0;
  background-color: #1a1a1a;
}

canvas {
  display: block;
  position: relative;
  zindex: 1;
  pointer-events: none;
}

button {
  padding: 5px 10px;
  font-size: 20px;
}

.scene {
  display: flex;
  position: relative;
  width: 100%;
  height: 100%;
  align-items: center;
  justify-content: center;
}

.scene>canvas {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.scene-content {
  position: relative;
  text-align: center;
  width: auto;
  height: auto;
  font-size: 10rem;
  font-family: Roboto;
  font-weight: 200;
  color: hsla(255, 50%, 100%, 1);
  animation: hue-shift 2s infinite linear;
}

.scene-content1 {
  position: relative;
  text-align: center;
  width: auto;
  height: auto;
  font-size: 10rem;
  font-family: Roboto;
  font-weight: 200;
  color: hsla(255, 50%, 100%, 1);
  animation: hue-shift 2s infinite linear;
}

.scene-content2 {
  position: relative;
  text-align: center;
  width: auto;
  height: auto;
  font-size: 6rem;
  font-family: Roboto;
  font-weight: 100;
  color: hsla(255, 50%, 50%, 1);
  animation: hue-shift 2s infinite linear;
}

.devices {
  margin-left: auto;
  margin-right: auto;
  text-align: center;
  color: hsla(255, 50%, 100%, 1);
  animation: hue-shift 2s infinite linear;
}

@keyframes hue-shift {
  0% {
    color: hsla(0, 80%, 80%, 1);
  }
  25% {
    color: hsla(120, 80%, 80%, 1);
  }
  75% {
    color: hsla(240, 80%, 80%, 1);
  }
  100% {
    color: hsla(360, 80%, 80%, 1);
  }
}

.buttonContainer {
  display: inline-block;
}

button {
  padding: 5px 10px;
  font-size: 20px;
}

.clicker+.circle {
  -webkit-animation: rotor 1.5s linear 0s infinite normal;
  -mox-animation: rotor 1.5s linear 0s infinite normal;
  -o-animation: rotor 1.5s linear 0s infinite normal;
  animation: rotor 1.5s linear 0s infinite normal;
}

.paused {
  -webkit-animation-play-state: paused !important;
  -moz-animation-play-state: paused !important;
  -o-animation-play-state: paused !important;
  animation-play-state: paused !important;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <link href='http://fonts.googleapis.com/css?family=Roboto:400,100,300,500,700,900' rel='stylesheet'>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
  <link href="https://unpkg.com/ionicons@4.2.0/dist/css/ionicons.min.css" rel="stylesheet">
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
  <link rel="stylesheet" href="css/style.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>

<body>
  <audio id="bubble_pop">
  <source src="mp3/pop.mp3" type="audio/mp3">
  Your browser does not support the audio element.
</audio>
  <div class="scene">
    <canvas id="canvas"></canvas>
    <div class="scene-content">
      <div class="devices">
        <i class="icon ion-ios-phone-portrait" style="font-size: 1.8em;"></i>
        <i class="icon ion-ios-watch" style="font-size: 1.6em;"></i>
      </div>
      <p class="scene-content1">Success!</p>
      <p class="scene-content2">Way to go! You can now use your device!</p>
    </div>
    <!--Hiding the message on initial page load-->
    <script type="text/javascript">
      $('.scene-content').hide();
    </script>
  </div>
  <p>
    <button id="stopButton">Stop</button>
    <button id="startButton">Drop it like its hot</button>
  </p>

</body>
<script>
 
</script>

</html>
Chris Gillett ответил: 13 июня 2018 в 03:46
+1 Чувак, большое спасибо за указание на это ... Я не мог понять, почему он не работал, когда я использовал функцию обратного вызова там, как вы упомянули. Я думал, что я делаю что-то неправильно, или где-то в JS я что-то сломал, но это делает ВСЕГО смысл, почему он сейчас не работает.

Дополнительное видео по вопросу: Попытка запускать одну функцию после другой с помощью JS

True JS 24. Callback функции

Создание сайта | Урок #14 - Проверка полей JS + Ajax + PHP отправка

Отправляем HTML формы через AJAX на JS/PHP