Анимация JS/CSS Запускается Дважды После Первого Цикла

#css #loops #animation #css-transitions #slideshow

Вопрос:

Я работал над этой страницей карусели (которая запускается кнопкой «ввод» на целевой странице). Он пролистывается просто отлично до тех пор, пока не завершится первый цикл, после чего анимация стекается (пока страница не перегрузится).

Это в основном неупорядоченный список <ul> внутри основного <div> , в котором перечислены изображения и видео.

В ДВУХ СЛОВАХ, мои анимации запускаются правильно, и мои классы хорошо переносятся во время первого цикла. Но во втором цикле что-то происходит. Первая страница отображается правильно, но второй элемент исчезает, потому что анимация, которая его вызывает, запускается дважды (проверяется путем добавления 'animationstart' журнала консоли).

ФУНКЦИИ:

  1. При входе из функции целевой страницы enterPage() :
    • первый элемент, представляющий собой видео, отображается и воспроизводится; затем
    • прослушиватель 'ended' событий, который затем запускает flipCurrentToNext() функцию.
  2. Функция flipCurrentToNext() :
    • обновляет переменные currentPage и a nextPage ;
    • приостанавливает currentPage , если это видео ( firstPage это видео);
    • добавляет класс перехода, который переворачивает currentPage влево;
    • отображает и анимирует nextPage переход в видовое окно справа;
    • он воспроизводит видео, если это видео, и просто отображает, если это фотография;
    • добавляет в 'animationend' список nextPage событий , который затем:
      а) удаляет переход и .current-page класс из перевернутого currentPage состояния ;
      б) добавляет .current-page класс в nextPage ;
      в) обновляет currentPage = nextPage ;
      г) обрабатывает перевернутую страницу как currentPage ;
      д) вызывает функцию, которая autoFlip() проходит через карусель.
  3. flipLastToFirst() функция выполняет то же самое, что и № 2, за исключением:
    • nextPage обменивается с firstPage и;
    • это autoFlip() не запускается, потому что каким-то образом enterPage() функция все еще запускает 'ended' прослушиватель событий видео.
  4. There are click handlers on transparent divs that users can use. I’m still not sure how I want these to override the autoFlip() s. (not really part of my question, but if you do have the answer, I’d love to know it!)
  5. There are also other functions like flipToPrevious() , flipFirstToLast() , but they’re basically the same as above.

THE CODE:

 function enterPage() {
  //some code that deals with the landing page

  let cover = document.querySelector('.firstPage');
  cover.style.display = "block";
  cover.play();
  cover.addEventListener('ended', () => {
    flipCurrentToNext();
    return;
  })
  return;
  //I thought adding return would somehow close the eventlistener.
  //I initially explored the possibility that 'ended' was also 
  //simultaneously calling flipToNext(), causing the
  //animation overload.
}


let currentPage = 
  content.querySelector('.current-page');
let nextPage =
  currentPage.parentElement.nextElementSibling.childNodes[1];


function autoFlip() {
  currentPage = content.querySelector('.current-page');

  if (currentPage.parentElement.nextElementSibling == null) {
    flipLastToFirst();
  } else {
    flipCurrentToNext();
  }

  clearTimeout();
  return;
}


function flipCurrentToNext() {

  currentPage =
    content.querySelector('.current-page');
  nextPage = 
    currentPage.parentElement.nextElementSibling.childNodes[1];
  //updates variables to stay current

  if (currentPage.childNodes[1].type == "video/mp4") {
    currentPage.pause();
    //I suspected if this triggers the 'ended'
    //eventlistener. Will it? If it does, how do I go around it?
    //I couldn't figure out how to integrate
    //a removeEventListener.
    currentPage.currentTime = 0;
  }

  currentPage.classList.add('flipOutLeft')
  //This transition class flips the current page out.

  nextPage.style.display = "block";

  nextPage.style.animation = "flipInRight 0.77s";
  //THIS is the animation that gets triggered twice after
  //the first loop. Then it stacks. I've console logged
  //nextPage, its classes and its IDs. It is one and the same.
  //
  //This animation is what flips the next page into the viewport.

  nextPage.addEventListener('animationend', () => {

    currentPage.style.display = "none";
    currentPage.classList.remove('flipOutLeft');
    currentPage.classList.remove('current-page');

    nextPage.classList.add('current-page');

    currentPage = nextPage;
    //above is an initial solution to handling fast clicks
    //not final

    if (currentPage.childNodes[1].type == "video/mp4") {
      currentPage = content.querySelector('.current-page');
      currentPage.play();

      currentPage.addEventListener('ended', () => {
        autoFlip(); //<--AUTOFLIP CALL for videos
        return; 
      })

    } else {
      setTimeout(autoFlip, 5555); //<--for photos
    }
    return;
  })
  return;
}

//This is the CLICK handler.
flipRight.addEventListener('click', () => {
  clearTimeout(autoFlip());
  currentPage = content.querySelector('.current-page');
  currentPage.removeEventListener('ended', flipCurrentToNext());
  //I can't tell if this helped.
  if (currentPage.classList.contains('lastPage') == true) {
    flipLastToFirst();
  } else {   
    flipCurrentToNext();
  }
})

//I've console-logged the hell out of the code.
//I couldn't find where I'm going wrong.

//JUST IN CASE you need to see the LastToFirst function:
function flipLastToFirst() {
  currentPage = content.querySelector('.current-page');
  let firstPage = currentPage.parentElement.parentElement.firstElementChild.childNodes[1];
  if (currentPage.childNodes[1].type == "video/mp4") {
      currentPage.pause();
      currentPage.currentTime = 0;
      muteButton.style.visibility = "hidden";
  }
  currentPage.classList.add('flipOutLeft');
  firstPage.style.display = "block";
  firstPage.style.animation = "flipInRight 0.77s";
  firstPage.addEventListener('animationend', () => {
    currentPage = content.querySelector('.current-page');
    currentPage.style.display = "none";
    currentPage.classList.remove('flipOutLeft');
    currentPage.classList.remove('current-page');
    firstPage.classList.add('current-page');
    currentPage = content.querySelector('.current-page');
    firstPage.play();
    muteButton.style.visibility = "visible";
    return;
  })
  return;
} 
 .carousel__content {        /*Unordered List*/
  padding: 0;
  margin: 0;
  list-style-type: none;
  overflow: hidden;
  height: 100vh;
}

.carousel__page {           /*List Item*/
  height: 100vh;
  float: left;
}

.carousel__page-item {
  position: absolute;
  display: none;
  height: 100vh;
  transition: all 0.55s ease-out;
  animation: all ease-out;
  animation-iteration-count: 1;  /*I tried - didn't work*/
}

.flipOutLeft {              /*Applied transition*/
  transform: translate(-150%, 0);
  opacity: 0;

@keyframes flipInRight {    /*Applied animation*/
  0%   {transform: translate(200%, 0)};
  100% {transform: translate(0, 0)}; 
 <main>
  <!--transparent navigation <buttons>-->
  <div>
    <ul class="carousel__content">

      <li class="carousel__page">

        <!--THIS VIDEO is what starts the carousel-->
        <video class="carousel__video carousel__page-item
          firstPage current-page" preload="auto" autoplay="true">
          <source src="" type="video/mp4">
        </video>

      </li>
      <li>
        <picture class="carousel__image carousel__page-item">
          <img /></picture>
      </li>

      <!--More are added just like this last picture.-->

    </ul>
  </div>
</main> 

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

Я начал писать код месяц назад, и я определенно чувствую, что у меня с головой все в порядке.

P.S. Я на 100% уверен, что в коде есть ненужные строки — не стесняйтесь указывать на них.

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

1. на данный момент, как мне кажется, ваш обработчик событий для animationend добавляется несколько раз. Возможно, потребуется удалить. Попытаюсь воссоздать в песочнице с кодом или что-то в этом роде.