【问题标题】:How to implement promises in vanilla javascript to wait for transitions to complete?如何在 vanilla javascript 中实现承诺以等待转换完成?
【发布时间】:2019-01-23 06:42:59
【问题描述】:

我在遍历项目列表并通过 vanilla javascript 淡入和淡出它们时遇到困难。假设我有一个字符串列表 ["cat", "ball", "bat", "mouse"]。

我想遍历这些项目并一一显示。例如,首先我需要显示“cat”,然后继续显示“bat”。为了做到这一点,我必须先等到“cat”淡入,等它淡出,然后再显示“bat”。目前,我只是在使用 for 循环,循环直接到列表“鼠标”的末尾,而不是等待其他元素完成淡入淡出。

为了解决这个问题,我知道我需要使用异步编程、回调、promise API 等,但我并没有真正使用这些东西太多,所以我不知道如何实现这个解决方案。非常感谢有关如何在“setInterval()”旁边使用异步编程的任何帮助或说明。

这是我的代码的 sn-p:

var textarr = ["cat", "ball", "bat", "mouse"]
for(let i=0; i<textarr.length; i++){
  var text_item = document.getElementById('text_item');
  text_item.style.opacity = 0;
  text_item.innerHTML = textarr[i];
  // problem lies here; this is skipping to end of the list (mouse)
  fadeIn(text_item);
}

//function borrowed from stack overflow to fadeIn elements

function fadeIn(element) {
    var op = 0.1;  // initial opacity
    element.style.display = 'block';
    var timer = setInterval(function () {
        if (op >= 1){
            clearInterval(timer);
        }
        element.style.opacity = op;
        element.style.filter = 'alpha(opacity=' + op * 100 + ")";
        op += op * 0.1;
    }, 100);
}

【问题讨论】:

  • 请在您的问题中发布相关代码sn-ps。
  • 没有承诺就开始。仅使用setTimeout(或转换事件处理程序,取决于动画的编码方式)和回调。使用递归方法遍历列表。一旦掌握了这些基础知识,就可以了解 Promise。
  • 这取决于你如何进行过渡。
  • 与promise不同,您可以使用简单的过渡结束事件处理程序来做到这一点。 developer.mozilla.org/en-US/docs/Web/Events/transitionend
  • 我对缺少代码 sn-ps 表示歉意 - 我已经编辑了问题以包含它们。谢谢!

标签: javascript asynchronous callback promise setinterval


【解决方案1】:

利用@RwwL 在cmets 中提到的transitionend 事件:

let display = document.getElementById('display');
const animals = ['dog', 'cat', 'mouse'];
let i = 0;

display.addEventListener('transitionend', function(event) {
  if (i < animals.length) {
    if (!display.classList.contains('fadeIn')) {
      display.innerHTML = animals[i++];
    }
    display.classList.toggle('fadeIn');
  }
}, false);

// Set timeout, otherwise the transition won't take effect (there are ways around this)
setTimeout(() => {
  display.classList.toggle('fadeIn');
}, 1000);
#display {
  color: #FFFFFF;
  transition: color 1s ease-in;
}

#display.fadeIn {
  color: #000000;
}
&lt;div id="display"&gt;Animal Names Here&lt;/div&gt;

【讨论】:

  • 非常感谢,这就是我要找的 :)
【解决方案2】:

最好的方法是使用一个队列,其中计时器从列表中选择项目而不是操作。在这种情况下,我使用 CSS 过渡对其进行编码以进行简单的淡入淡出。

// Made it a function so you could use 
// it more than once on same page
function changeText (arr, elem, startIndex) {
  // holds active slide
  let current = startIndex || 0
  // Called when we what to show the current word
  const update = function () {
    // set the word on the page
    elem.innerHTML = arr[current]
    // Add the class to start transition
    elem.classList.add('fadeIn')
    // How long you want the word to stay on the screen
    // When timer executes it calls function to reverse
    // the annimation
    window.setTimeout(next, 3000)  // 3 seconds
  }
  // Called to do the reverse animation and update the step
  const next = function () {  
    // remove the class so goes back to zero
    elem.classList.remove('fadeIn')
    // update what slide we are on
    current++
    // If we are over the limit, than restart
    if (current===arr.length) {
      current = 0  // back to first slide
    }
    // How long do you want for the fade out transition to
    // take to execute. 
    window.setTimeout(update, 300);  // 300 milliseconds
  }
  // initialize it so first word shows up
  update();
}

var textarr = ["cat", "ball", "bat", "mouse"]
changeText(textarr, document.querySelector('.text1'))

changeText(textarr, document.querySelector('.text2'), 3)
.text {
  opacity: 0;  
  transition: opacity .3s ease-in-out;
}

.fadeIn {
  opacity: 1;
  transition: opacity 2s ease-in-out;
}
<h1>One</h1>
<div class="text text1"></div>
<h2>Another one</h2>
<div class="text text2"></div>

【讨论】:

    猜你喜欢
    • 2017-06-17
    • 2018-03-05
    • 2016-10-16
    • 1970-01-01
    • 2018-08-03
    • 2020-10-31
    • 1970-01-01
    相关资源
    最近更新 更多