Jquery:数组中的最后一个图像重复两次,为什么?

时间:2014-05-14 16:16:04

标签: javascript jquery arrays function setinterval

在我的数组'bg'中,当'fadebg'函数到达时,最后一项/图像重复两次, 任何人都可以回答我为什么会发生这种情况以及如何解决这个问题?

var bg = [];
bg[0] = "resources/images/bg/1.jpg";
bg[1] = "resources/images/bg/2.jpg";
bg[2] = "resources/images/bg/3.jpg";
bg[3] = "resources/images/bg/4.jpg";
bg[4] = "resources/images/bg/5.jpg";
bg[5] = "resources/images/bg/6.jpg";
bg[6] = "resources/images/bg/7.jpg";
bg[7] = "resources/images/bg/8.jpg";
bg[8] = "resources/images/bg/9.jpg";
bg[9] = "resources/images/bg/10.jpg";

var i = 0;

setInterval(fadebg, 10000);

function fadebg() {
    if (i < 10) {
        $('#bg').css({ opacity: 0 });
        setTimeout(function () {
            $('#bg').attr('src', bg[i]).css({ opacity: 1 })
        }, 300);
    };
    if (i == 10) {
        i = -1;
        $('#bg').css({ opacity: 0 });
        setTimeout(function () {
            $('#bg').attr('src', bg[i]).css({ opacity: 1 })
        }, 300);
        };
    i++;
};

顺便说一句,是否有人知道这个函数'fadebg'的缩写版本?

4 个答案:

答案 0 :(得分:3)

这是因为fadebg内的函数靠近变量 i,而不是创建函数时的值。他们使用运行时的值。这是经典的关闭错误。更多:Closures are not complicated

要使用创建函数时的值,您必须使用i以外的其他内容。我通常使用构建器函数:

function buildTheCallback(src) {
    return function () {
        $('#bg').attr('src', src).css({ opacity: 1 })
    };
}

...你这样使用:

setTimeout(buildTheCallback(bg[i]), 300);

现在,我们给出的函数setTimeout(调用buildTheCallback返回的函数)会关闭我们传递给它的src参数,但不会得到改变。


一个较短的版本,这些内容(未经测试 嘿,你知道什么,it works [我将10000毫秒缩短到1000毫秒进行测试] ):

(function() {
    var bg = [
        "resources/images/bg/1.jpg",
        "resources/images/bg/2.jpg",
        "resources/images/bg/3.jpg",
        "resources/images/bg/4.jpg",
        "resources/images/bg/5.jpg",
        "resources/images/bg/6.jpg",
        "resources/images/bg/7.jpg",
        "resources/images/bg/8.jpg",
        "resources/images/bg/9.jpg",
        "resources/images/bg/10.jpg"
        ];
    var bgIndex = -1;
    setInterval(fadeBg, 10000);

    function fadeBg() {
        bgIndex = (bgIndex + 1) % bg.length;
        $('#bg').css({ opacity: 0 });
        setTimeout(showBg, 300);
    }
    function showBg() {
        $('#bg').attr('src', bg[bgIndex]).css({ opacity: 1 })
    }
})();

(我假设除了数字之外,图像的真实路径不相同;如果是,则可以使其明显缩短。)

但如果是我,我会褪色而不是突然转向opacity: 0 / opacity: 1Live Example

(function() {
    var bg = [
        "resources/images/bg/1.jpg",
        "resources/images/bg/2.jpg",
        "resources/images/bg/3.jpg",
        "resources/images/bg/4.jpg",
        "resources/images/bg/5.jpg",
        "resources/images/bg/6.jpg",
        "resources/images/bg/7.jpg",
        "resources/images/bg/8.jpg",
        "resources/images/bg/9.jpg",
        "resources/images/bg/10.jpg"
        ];
  var bgIndex = -1;
  setInterval(fadeBg, 10000);

  function fadeBg() {
    bgIndex = (bgIndex + 1) % bg.length;
    $('#bg').fadeTo("300", 0, showBg);
  }
  function showBg() {
    $('#bg').attr('src', bg[bgIndex]).fadeTo("300", 1);
  }
})();

答案 1 :(得分:3)

这是一个更简单的版本:

(function() {
    var bgIndex = 0;
    setInterval(function() {
        var item = $('#bg').css({ opacity: 0 });
        setTimeout(function() {
            item.attr("src", bg[++bgIndex % bg.length]);
        }, 300);
    }, 10000);
})();

它使用%技巧允许索引循环遍历数组,而不会离开数组的边界。

此外,这解决了您遇到的原始问题,因为索引变量仅在您使用索引时才会递增,因此在变量增加和使用时没有时间延迟问题。

增强功能摘要:

  1. 使用% bl.length技巧简化代码以保持在数组的范围内,并将您的两个代码分支折叠为仅一个分支。
  2. 仅在我们即将使用它时增加数组索引,以便在增加时没有时间问题。
  3. 包裹在IIFE中,因此没有全局变量。全球i是一种非常危险的做法。在var循环中忘记for (i = 0;...)的一行代码,现在您的全局i会被删除。
  4. 保存$('#bg')的价值,这样您就不会在短时间内重新开始。

答案 2 :(得分:2)

尝试:

function fadebg() {
    if( i == 10 ){
      i = -1;
    }
    $('#bg').css({ opacity: 0 });
    setTimeout(function () {
      $('#bg').attr('src', bg[i]).css({ opacity: 1 })
    }, 300);
    i++;
};

答案 3 :(得分:0)

你可以做这样的事情来缩小你的功能:

bg.each(function(i){
    $('#bg').css({opacity:0});
    setTimeout(function () {
        $('#bg').attr('src', bg[i]).css({ opacity: 1 })
    }, 300);
});

我还没有测试过,但可能需要考虑一下。