Как добавить прослушиватель событий в элемент после определенного условия c? - PullRequest
2 голосов
/ 25 февраля 2020

У меня есть элемент игрового поля ti c -ta c, который появляется в пользовательском интерфейсе с 5-секундной анимацией (непрозрачность 0 -> 100, постепенно исчезает в стиле), и я хочу, чтобы он стал активным после нажатия кнопки анимация заканчивается не сразу после загрузки страницы. Как я могу сделать это с ванильными javascript слушателями событий?

const cells = document.querySelectorAll('.cell');

cells.forEach(cell => cell.addEventListener('click', (e) => {
  if (board[e.target.getAttribute("data-render")] === '') {
    origBoard[e.target.getAttribute("data-render")] = huPlayer;
    render();
    setTimeout(aiMove, 700);
}
}));

Это работает хорошо, но мне нужно активировать слушатель событий сразу после выполнения анимации или функции "aiMove", описанной выше. Я не хочу, чтобы пользователи могли щелкать ячейки до окончания анимации. Анимация CSS только с @ ключевыми кадрами.

@keyframes fade-in {
    0%   { opacity: 0; }
    100% { opacity: 1; }
  }

Ответы [ 3 ]

4 голосов
/ 25 февраля 2020

Вы можете сделать это многими способами. Вот несколько примеров.

Использование флага и setTimeout

Это означает, что ваш скрипт должен знать продолжительность.

const cells = document.querySelectorAll('.cell');
let animationComplete = false;

setTimeout(() => animationComplete = true, 5000);

cells.forEach(cell => cell.addEventListener('click', (e) => {
  if (animationComplete) {
    console.log("You can click because the animation is over");
  }
}));
<div class="cell"></div><div class="cell"></div><div class="cell"></div><div class="cell"></div><style>.cell{padding: 20px; background: red; display: inline-block; animation: fadeIn 5s;}@keyframes fadeIn{from{opacity: 0}to{opacity: 1}}</style>

Использование setTimeout и ожидание перед настройкой прослушивателя событий

Это означает, что ваш сценарий должен знать продолжительность.

const cells = document.querySelectorAll('.cell');

setTimeout(() => {
  cells.forEach(cell => cell.addEventListener('click', (e) => {
    console.log("You can click because the animation is over");
  }));
}, 5000);
<div class="cell"></div><div class="cell"></div><div class="cell"></div><div class="cell"></div><style>.cell{padding: 20px; background: red; display: inline-block; animation: fadeIn 5s;}@keyframes fadeIn{from{opacity: 0}to{opacity: 1}}</style>

Использование флага и события animationend

Не нужно знать продолжительность! Измените его в CSS, и JS будет следовать.

const cells = document.querySelectorAll('.cell');
let animationComplete = false;

cells[0].addEventListener(whichAnimationEvent(), () => animationComplete = true);

cells.forEach(cell => cell.addEventListener('click', (e) => {
  if (animationComplete) {
    console.log("You can click because the animation is over");
  }
}));

// The name of the event depends on the browser
function whichAnimationEvent(){
  var t, el = document.createElement("fakeelement");

  var animations = {
    "animation"      : "animationend",
    "OAnimation"     : "oAnimationEnd",
    "MozAnimation"   : "animationend",
    "WebkitAnimation": "webkitAnimationEnd"
  }

  for (t in animations){
    if (el.style[t] !== undefined){
      return animations[t];
    }
  }
}
<div class="cell"></div><div class="cell"></div><div class="cell"></div><div class="cell"></div><style>.cell{padding: 20px; background: red; display: inline-block; animation: fadeIn 5s;}@keyframes fadeIn{from{opacity: 0}to{opacity: 1}}</style>

Использование события animationend и ожидание перед настройкой прослушивателя события

Не нужно также знать продолжительность .

const cells = document.querySelectorAll('.cell');

cells[0].addEventListener(whichAnimationEvent(), () => {
  cells.forEach(cell => cell.addEventListener('click', (e) => {
    console.log("You can click because the animation is over");
  }));
});

// The name of the event depends on the browser
function whichAnimationEvent(){
  var t, el = document.createElement("fakeelement");

  var animations = {
    "animation"      : "animationend",
    "OAnimation"     : "oAnimationEnd",
    "MozAnimation"   : "animationend",
    "WebkitAnimation": "webkitAnimationEnd"
  }

  for (t in animations){
    if (el.style[t] !== undefined){
      return animations[t];
    }
  }
}
<div class="cell"></div><div class="cell"></div><div class="cell"></div><div class="cell"></div><style>.cell{padding: 20px; background: red; display: inline-block; animation: fadeIn 5s;}@keyframes fadeIn{from{opacity: 0}to{opacity: 1}}</style>
1 голос
/ 25 февраля 2020

Другим способом предотвращения срабатывания щелчков мыши на анимированном элементе является использование свойства pointer-events CSS.

Применение pointer-events:none; к элементу предотвращает влияние событий щелчка. В вашем случае вы можете добавить это в класс CSS, который задает анимацию на игровом поле, что, в свою очередь, предотвратит события щелчка во время начальной анимации игрового поля.

Вот фрагмент кода, иллюстрирующий эту идею:

const gameBoard = document.querySelector(".gameBoard");

gameBoard.addEventListener("click", () => {
  alert("I respond to click events");
});

gameBoard.classList.add("animate");
console.log("1. The game board does not respond to click interaction");

setTimeout(() => {
    console.log("2. The game board will now respond to click interaction");
   gameBoard.classList.remove("animate");
}, 5000);
@keyframes fade-in {
    0%   { opacity: 0; }
    100% { opacity: 1; }
  }
 
.cell {
  background:red;
}
 
.gameBoard {
  display:grid;
  grid-gap:2px;
  grid-template-rows:repeat(2, 1fr);
  grid-template-columns:repeat(2, 1fr);
  
  background:yellow;
  width:100px;
  height:100px;
}

.gameBoard.animate {
  /* Prevent click events from firing on the gameboard
  while animation modifier class is applied */
  pointer-events:none;
  animation: fade-in 5s;
}
<div class="gameBoard">
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
</div>
0 голосов
/ 25 февраля 2020

Вы можете создать функцию, которая возвращает этот l oop, завернутый в setTimout.

function awaitAnimation() {
  return setTimout(() => (cells.forEach(cell => cell.addEventListener('click', (e) => {
    if (board[e.target.getAttribute("data-render")] === '') {
      origBoard[e.target.getAttribute("data-render")] = huPlayer;
      render()
      setTimeout(aiMove, 700)
    }
  }))), 5000);
}
...