Есть ли альтернатива использованию setInterval () для анимации исчезающего текста в javascript при итерации по объектам в массиве? - PullRequest
0 голосов
/ 06 августа 2020

Сейчас я пытаюсь постепенно увеличивать и уменьшать текст из массива с помощью функции setInterval (). Моя функция init () просматривает массив и вызывает функцию FadeInThenFadeOut () для применения анимации затухания для каждого объекта в массиве; однако во время отладки я заметил, что при вызове setInterval () моя программа переходит к следующему объекту в массиве и пропускает код для применения анимации затухания.

Насколько я понимаю, setInterval () задерживает обратный вызов для применения анимации затухания на 50 мс (миллисекунд), поэтому я считаю, что это приводит к пропуску кода. Может ли кто-нибудь помочь мне найти способ завершить выполнение моей функции FadeInThenFadeOut () перед переходом к следующему объекту в массиве

let quotes = [
  {
      "id": 1,
      "text": "text1",
      "author": "author1"
  },
  {
      "id": 2,
      "text": "text2",
      "author": "author2"
  },
  {
      "id": 3,
      "text": "text3",
      "author": "author3"
  }
]; 

const quotePlacement = document.createElement('div'); 
quotePlacement.classList.add('text-example');

function init() {

  for(let quoteIndex = 0; quoteIndex < quotes.length; quoteIndex++){

    AssignAndAppendElement(quotes[quoteIndex].text, quotes[quoteIndex].author);  

    FadeInThenFadeOut();

    // now wait for FadeInThenFadeOut() to finish
    // then iterate to the next quoteindex

  }
 
}
 
let elementOpacity = 0; 

const callBackTimeInterval = 50;

function FadeInThenFadeOut() {

  const timerId = setInterval(function() {

    IncreaseOpacity();  

    if(elementOpacity >= 1){
      
      clearInterval(timerId); 
      SetElementVisibility(true); 
       
      FadeOut(); 
      ResetQuotePlacement();
    }
    quotePlacement.style.opacity = elementOpacity; 
  }, callBackTimeInterval); 
 
}

function FadeOut() {

  const timerId = setInterval(function() {

    DecreaseOpacity();

    if(elementOpacity <= 0){
      clearInterval(timerId); 
      SetElementVisibility(false); 
       
    }
    quotePlacement.style.opacity = elementOpacity; 
  }, callBackTimeInterval); 
}

function DecreaseOpacity() {
  elementOpacity -= 0.025; 
}

function IncreaseOpacity(){
  elementOpacity += 0.025;  
}

function SetElementVisibility(visibility) {

  if(visibility){ 
    quotePlacement.style.opacity = 1; 
    elementOpacity = 1; 
    return; 
  }  
  elementOpacity = 0; 
  
}

function AssignAndAppendElement(quoteText, author) {
 
  quotePlacement.innerHTML = "<h1> <q>" + quoteText + "</q> - " + author + "</h1>";
  quotePlacement.style.opacity = 0;

  document.body.appendChild(quotePlacement); 

}

function ResetQuotePlacement() {
  quotePlacement.innerHTML = ""; 
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="styles.css">
    <script defer src="main.js"></script>
    <!-- <link rel="stylesheet" href="../bootstrap.css"> -->
    <title>Inspirational Quotes</title>
</head>
<body onload="init()">
</body>
</html>

Ответы [ 2 ]

1 голос
/ 06 августа 2020

Я нашел проблему. Вы вызывали функцию сброса не в то время

function FadeInThenFadeOut() {

  const timerId = setInterval(function() {

    IncreaseOpacity();  

    if(elementOpacity >= 1){
      
      clearInterval(timerId); 
      SetElementVisibility(true); 
       
      FadeOut(); 
      ResetQuotePlacement(); // <---------------- this line
    }
    quotePlacement.style.opacity = elementOpacity; 
  }, callBackTimeInterval); 
 
}

Если я переместил ее в функцию FadeOut, она работает правильно

Кроме того, чтобы дождаться завершения каждой анимации затухания, вы можете просто объявите функцию showNextQuote и вызовите ее в конце функции FadeOut.

Вот рабочий код:

let quotes = [{
    "id": 1,
    "text": "text1",
    "author": "author1"
  },
  {
    "id": 2,
    "text": "text2",
    "author": "author2"
  },
  {
    "id": 3,
    "text": "text3",
    "author": "author3"
  }
];

const quotePlacement = document.createElement('div');
quotePlacement.classList.add('text-example');

function init() {

  showNextQuote();

}

let quoteIndex = 0;

function showNextQuote() {
  if (quoteIndex >= quotes.length) return; //alternatively, set it back to 0 to keep looping
  ResetQuotePlacement();
  AssignAndAppendElement(quotes[quoteIndex].text, quotes[quoteIndex].author);
  quoteIndex++;
  FadeInThenFadeOut();
}

let elementOpacity = 0;

const callBackTimeInterval = 50;

function FadeInThenFadeOut() {

  const timerId = setInterval(function() {

    IncreaseOpacity();

    if (elementOpacity >= 1) {

      clearInterval(timerId);
      SetElementVisibility(true);

      FadeOut();
    }
    quotePlacement.style.opacity = elementOpacity;
  }, callBackTimeInterval);

}

function FadeOut() {

  const timerId = setInterval(function() {

    DecreaseOpacity();

    if (elementOpacity <= 0) {
      clearInterval(timerId);
      SetElementVisibility(false);
      showNextQuote();
    }
    quotePlacement.style.opacity = elementOpacity;
  }, callBackTimeInterval);
}

function DecreaseOpacity() {
  elementOpacity -= 0.025;
}

function IncreaseOpacity() {
  elementOpacity += 0.025;
}

function SetElementVisibility(visibility) {

  if (visibility) {
    quotePlacement.style.opacity = 1;
    elementOpacity = 1;
    return;
  }
  elementOpacity = 0;

}

function AssignAndAppendElement(quoteText, author) {

  quotePlacement.innerHTML = "<h1> <q>" + quoteText + "</q> - " + author + "</h1>";
  quotePlacement.style.opacity = 0;

  document.body.appendChild(quotePlacement);

}

function ResetQuotePlacement() {
  quotePlacement.innerHTML = "";
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="styles.css">
  <script defer src="main.js"></script>
  <!-- <link rel="stylesheet" href="../bootstrap.css"> -->
  <title>Inspirational Quotes</title>
</head>

<body onload="init()">
</body>

</html>

В качестве альтернативы вы можете использовать свойство перехода css. Это немного упрощает работу. Вот быстрый пример:

const quotes = ["Quote 1", "Quote 2", "Quote 3"];
const el = document.getElementById("holder");
el.style.opacity = 0;

let currentIndex = 0;
let currentShown = false;

const intervalID = setInterval(() => {
  if (currentIndex >= quotes.length) {
    clearInterval(intervalID);
    return;
  }
  if (!currentShown) {
    el.style.opacity = 1;
    el.innerText = quotes[currentIndex];
    currentShown = true;
  } else {
    el.style.opacity = 0;
    currentShown = false;
    currentIndex++;
  }
}, 2000);
#holder {
  transition: opacity 1.9s;
}
<h1 id="holder"></h1>
0 голосов
/ 06 августа 2020

css с событием animationend и без использования setInterval ()

Я использовал стандартный метод html для котировок с аутентификацией.

l oop перезапускается для следующего элемента, как только происходит событие animationend

const DomParser = new DOMParser()
const quotes = 
    [ { id: 1, text: 'text1', author: 'author1' } 
    , { id: 2, text: 'text2', author: 'author2' } 
    , { id: 3, text: 'text3', author: 'author3' } 
    ] 
const quotePlacement = document.createElement('div')
      quotePlacement.index = -1

function newQuote(txt,auth)
  {
  let elm = `<blockquote>
              <p>${txt}</p>
              <footer>${auth}</footer>
             </blockquote>`
  return DomParser.parseFromString( elm, 'text/html').body.firstChild
  }
function nextQuoteLoop()
  {
  quotePlacement.index = ++quotePlacement.index % quotes.length
  let { text, author } = quotes[quotePlacement.index]
  if (quotePlacement.firstChild) 
    { quotePlacement.firstChild.remove() }
  quotePlacement.appendChild( newQuote(text,author ))
  quotePlacement.firstChild.classList.add('fade-in-out')
  }

// main
document.body.appendChild(quotePlacement)
quotePlacement.onanimationend = nextQuoteLoop 

nextQuoteLoop() // start the first one...
.fade-in-out  { animation: fadeInOut ease 7s; }
@keyframes fadeInOut {
  0%   { opacity:0; }
  50%  { opacity:1; }
  100% { opacity:0; }
}

/* classic blockquote */
blockquote {
  padding: 6px 16px;
  border: none;
  quotes: "\201C\2009" "\2009\201D";
  display: block;
  float: right;
  opacity:0; 
}
blockquote p { 
  font-size: 36px;
  padding: 0 16px 0 0;
  text-indent: -12px;
  color: #251487;     
  font-style: italic;
  margin-bottom: 0.3em;
}
blockquote p:before {
  content: open-quote;
  font-weight: bold;
  font-size: 40px;
  line-height: 32px;
}
blockquote p:after {
  content: close-quote;
  font-weight: bold;
  font-size: 40px;
  line-height: 32px;
}
blockquote footer {
  text-align: right;
  padding-right: .7em;
  font-style: oblique;
  color: #2d0068;
}
...