使用链接的JavaScript承诺淡入/淡出图像

时间:2019-07-17 11:58:35

标签: javascript es6-promise

我正在尝试创建非JQuery图像幻灯片,其中图像根据计时器淡入/淡出。经过大量研究,我相信JavaScript的Promise功能可以做到这一点,但这并不完全正确。

我的问题是淡入和淡出功能似乎是同时发生的,因此图像只是闪烁。我正在尝试改编使用then()链接函数的许多示例,但是显然有些错误。

我的逻辑是:

  1. 在页面加载时显示初始图片(通过CSS规则)
  2. 淡出
  3. 更改背景图片网址
  4. 淡入

我的online example is here,JavaScript在这里:

// Background images to show
var arr_Images = [
    'https://cdn.pixabay.com/photo/2015/08/24/12/53/banner-904884_960_720.jpg',
    'https://cdn.pixabay.com/photo/2016/11/19/22/52/coding-1841550_960_720.jpg',
    'https://cdn.pixabay.com/photo/2014/05/27/23/32/matrix-356024_960_720.jpg'
];

var cycleImage = document.getElementById("cycleImage");

// Preload images
for(x = 0; x < arr_Images.length; x++)
{
  var img = new Image();
    img.src = arr_Images[x];
}

function fadeOutPromise(element, nextBgImgUrl) {
    console.log("Fading out");
    return new Promise(function(resolve) {
        var op = 1;  // initial opacity
        var timer1 = setInterval(function () {
            if (op <= 0.1){
                clearInterval(timer1);
                element.style.display = 'none';
                cycleImage.style.backgroundImage = "url('" + nextBgImgUrl + "')";
            }
            element.style.opacity = op;
            element.style.filter = 'alpha(opacity=' + op * 100 + ")";
            op -= op * 0.1;
        }, 100);
        resolve("Faded In");
    });
}

function fadeInPromise(element) {
    console.log("Fading in");
    return new Promise(function(resolve) {
        var op = 0.1;  // initial opacity
        element.style.display = 'block';
        var timer2 = setInterval(function () {
            if (op >= 1){
                clearInterval(timer2);
            }
            element.style.opacity = op;
            element.style.filter = 'alpha(opacity=' + op * 100 + ")";
            op += op * 0.1;
        }, 10); 
        resolve("Faded Out");
    });
}

function slideShow() {

    // Loop background image using array
    var i = 0;
    var delay = 3000;

    // Loop
    let imageLoopTimer = setTimeout(function tick() {

        fadeOutPromise(cycleImage, arr_Images[i]).then(
            fadeInPromise(cycleImage).then(function() {
                i++;
                if ( i >= arr_Images.length) { i = 0; }
                imageLoopTimer = setTimeout(tick, delay);               
            })
        );

    }, delay);

}

slideShow();

有人可以先解释出什么问题,然后提供解决方案吗?

2 个答案:

答案 0 :(得分:3)

您快到了。问题是您如何履行诺言。 您打算在淡入淡出功能中执行的操作是:
-创造承诺
-间隔执行逻辑
-兑现诺言

但是您可以立即解决承诺,而一旦完成淡入淡出操作,就应该解决承诺:

function fadeInPromise(element) {
    console.log("Fading in");
    return new Promise(function(resolve) {
        var op = 0.1;  // initial opacity
        element.style.display = 'block';
        var timer2 = setInterval(function () {
            if (op >= 1){
                clearInterval(timer2);
                resolve():  // Fade is done here
            }
            element.style.opacity = op;
            element.style.filter = 'alpha(opacity=' + op * 100 + ")";
            op += op * 0.1;
        }, 10); 
    });
}

淡入淡出

另一个闪烁的提示 如果要获得平滑效果,则不应经常更改不透明度。在CSS中,已经有“ transition”属性。因此,您应该在过渡时执行以下操作:
-显示不透明度为1的图像
-将opactiy设置为0
-ms之后,更改网址并将不透明度设置为1

答案 1 :(得分:1)

setInterval()作为后台任务运行,因此resolve()将在timer2初始化后立即被触发。

  • 这与运行async操作非常相似,但与awaiting不同 它。
  • 或者可以保证,就像调用function返回一个Promise一样,但是想要访问数据而没有.then()回调

您需要在if (op >= 1)部分内解决您的承诺,以便在发生淡入/淡出后实际解决该承诺。

检查this snippet中您的更新版本。承诺在setInterval()内部解决。

以下是直接代码段的相关JavaScript代码:

function fadeOutPromise(element, nextBgImgUrl) {
    console.log("Fading out"+i);
    return new Promise(function(resolve, reject) {
        element.style.opacity = 0;
        setTimeout(() => {
            console.log("Fading out done"+i);
            element.style.backgroundImage = "url('" + nextBgImgUrl + "')";
            resolve();
        }, 1000);
    });
}

function fadeInPromise(element) {
    console.log("Fading in"+i);
    return new Promise(function(resolve, reject) {
        element.style.opacity = 1;
        setTimeout(resolve, 1000);
    });
}

var i = 0;
var delay = 3000;

function slideShow() {

    // Loop background image using array

    // Loop
    let imageLoopTimer = setTimeout(() => tick(), delay);

}

function tick() {

    fadeOutPromise(cycleImage, arr_Images[i]).then(() =>
        fadeInPromise(cycleImage).then(function() {
            i++;
            if ( i >= arr_Images.length) { i = 0; }
            imageLoopTimer = setTimeout(() => tick(), delay);               
        })
    );

}

编辑(具有过渡不透明度)

我有edited the snippet,现在可以在不透明的情况下进行过渡了。