多个 jQuery 幻灯片不会保持同步

Multiple jQuery slideshows won't stay in sync

我正在使用一个简单的 jQuery 脚本来 运行 一个 fade-in/out 幻灯片。 (我是 jQ 的 nubee。)我正在 运行ning 幻灯片放映的 3 个实例来控制 3 个单独的幻灯片区域。幻灯片使用淡入、延迟和淡出计时。以下是每个脚本的控制代码行:

slides.eq(slideCount).fadeIn(1000).delay(6000).fadeOut(1000, function(){
slides.eq(slideCount).fadeIn(2250).delay(3500).fadeOut(2250, function(){
slides.eq(slideCount).fadeIn(3000).delay(2000).fadeOut(3000, function(){

想法是每张幻灯片的总屏幕时间为 8 秒。开始时很好,但如果我让它 运行 一段时间,3 张幻灯片就会不同步。这破坏了页面的布局。我可以看到,我的假设是将淡入、延迟和淡出时间加在一起,但有一个小增量是有缺陷的。有谁知道是否有调整来纠正这个问题?

您可以在此处查看当前的幻灯片:Slideshow。如果您观看显示屏几分钟就没事了,可能需要大约 15 分钟才能开始不同步。一种解决方案是让页面在 x 次迭代后刷新。有没有办法将其添加到脚本中?任何想法将不胜感激。

完整脚本如下:

$(function() {
  var slides = $('.slideShowA>li');
  var slideCount = 0;
  var totalSlides = slides.length;
  var slideCache = [];

  (function preloader() {
    if (slideCount < totalSlides) {
      // Load Images
      slideCache[slideCount] = new Image();
      slideCache[slideCount].src = slides.eq(slideCount).find('img').attr('src');
      slideCache[slideCount].onload = function() {
        slideCount++;
        preloader();
      }
    } else {
      // Run the slideshow
      slideCount = 0;
      SlideShow();
    }
  }());

  function SlideShow() {
    // Your code goes here
    slides.eq(slideCount).fadeIn(1000).delay(6000).fadeOut(1000, function() {
      slideCount < totalSlides - 1 ? slideCount++ : slideCount = 0;
      SlideShow();
    });
  }
});

您需要将三个单独的幻灯片视为一次显示三个图像的幻灯片。这应该不难,因为三个列表的图片数量相同。

我不确定这是否重要,但您也可以尝试异步预加载图像。也就是说,您可以一次加载所有图像,而不是等待每个图像都加载完再加载下一个图像。您可以使用 JQuery 的 Deferred 对象在它们全部加载后执行代码。

假设您的 HTML 看起来像这样:

<div id="media-col">
    <div>
        <ul>
            <li><img ... /></li>
            <li><img ... /></li>
            <li><img ... /></li>
            <li><img ... /></li>
        </ul>
    </div>
    <div>
        <ul>
            <li><img ... /></li>
            <li><img ... /></li>
            <li><img ... /></li>
            <li><img ... /></li>
        </ul>
    </div>
    <div>
        <ul>
            <li><img ... /></li>
            <li><img ... /></li>
            <li><img ... /></li>
            <li><img ... /></li>
        </ul>
    </div>
</div>

你有以下 CSS:

#media-col li {
    opacity: 0;
    display: none;
}

您的代码可能如下所示:

$(function() {
    var TIMES = [
        { preDelay:    0, fadeIn: 3000, delay: 2000, fadeOut: 3000 },
        { preDelay: 1500, fadeIn:  500, delay: 4000, fadeOut:  500 },
        { preDelay: 1000, fadeIn: 1000, delay: 4000, fadeOut: 1000 }
    ];

    var $container = $('#media-col');

    // This function preloads an image and returns a Deferred object that is resolved
    // when the image's onload function is called.
    function preloadImage(url) {
        return $.Deferred(function(deferred) {
            var image = new Image();
            image.src = url;
            image.onload = function() {
                image.onload = null;
                deferred.resolve(image);
            }
        });
    }

    // Asynchronously preload all the images for the slideshows.
    var preloads = $container.find('img').map(function() {
        return preloadImage($(this).attr('src'));
    }).get();

    // This will start the slideshow when all the images have been preloaded.
    $.when.apply($, preloads).done(function() {
        var $lists = $container.find('ul'),
            slideCount = $lists.first().children().length;
        (function showSlide(slideIndex) {
            var $items = $lists.children(':nth-child(' + slideCount + 'n - ' + (slideCount - 1 - slideIndex) + ')');
            var promises = $items.show().map(function(i) {
                var t = TIMES[i];
                return $(this).delay(t.preDelay).fadeTo(t.fadeIn, 1).delay(t.delay).fadeTo(t.fadeOut, 0).promise();
            });
            $.when.apply($, promises).done(function() {
                $items.hide();
                showSlide((slideIndex + 1) % slideCount);
            });
        })(0);
    });
});

为了同步动画,上面的代码使用 $.when().promise() returns 一个承诺,当 JQuery 对象上的动画是完成..

上面的代码没有使用 .fadeOut(),而是使用了 .fadeTo()。然后 .hide() 可以在所有动画完成后调用。这样,所有项目都会同时隐藏。这也允许 "pre" 延迟。如果您不想要,可以轻松将其删除。

jsfiddle