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

时间:2015-06-08 22:36:18

标签: javascript jquery slideshow sync timing

我正在使用一个简单的jQuery脚本来运行淡入/淡出幻灯片。 (我在jQ是个小丑。)我正在运行幻灯片放映的3个实例来控制3个单独的幻灯片区域。幻灯片定时为fadeIn,delay和fadeOut。以下是每个脚本的控制代码行:

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张幻灯片就会失去同步。这破坏了页面的布局。我可以看到我的假设是将fadeIn,delay和fadeOut时间加在一起会有一个小的增量。有没有人知道是否有调整来纠正这个问题?

您可以在此处查看当前的幻灯片: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();
    });
  }
});

1 个答案:

答案 0 :(得分:2)

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

我不确定它是否重要,但您也可以尝试异步预加载图像。也就是说,不是在加载下一个图像之前等待每个图像加载,而是可以一次加载它们。您可以使用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()返回在JQuery对象上的动画完成时解析的promise的事实。

上述代码使用.fadeOut(),而非使用.fadeTo()。然后,当所有动画完成时,可以调用.hide()。这样,所有项目都会同时隐藏。这也允许“预”延迟。如果您不想这样,可以轻松将其删除。

jsfiddle