2016-12-31 85 views
1

我一直在使用jQuery 3.1.1开发自己的JavaScript幻灯片。它工作正常,但由于某种原因,过渡动画不平滑。当只有两张照片时,它可以正常工作,但是一旦我添加了三张照片,它根本不起作用。JavaScript幻灯片不顺畅

我做了这个小提琴,如果有人可以提供一些有识之士将不胜感激。

!function($) { 
 
    "use strict"; 
 
    $.slideshow = function(container) { 
 
    let $container = $(container); 
 
    let children = $container.find('.slide').length; 
 
    $container.find('.slide').each(function(index) { 
 
     let zIndex = 210 - index; 
 
     let bg = $(this).data('bg'); 
 
     $(this).css('background-image', 'url(' + bg + ')'); 
 
    }); 
 
    let settings = { 
 
     'transition': 500, 
 
     'delay': 6000, 
 
    }; 
 
    let currentSlide = 0; 
 
    $.fn.showNext = function() { 
 
     let nextSlide = ((currentSlide + 1) < children) ? (currentSlide + 1) : 0; 
 
     let $current = $container.find('.slide:nth-child(' + (currentSlide + 1) + ')'); 
 
     let $next = $container.find('.slide:nth-child(' + (nextSlide + 1) + ')'); 
 
     $current.animate({ 
 
     'opacity': 0 
 
     }, settings.transition); 
 
     setTimeout(function() { 
 
     $current.css('z-index', 200); 
 
     $current.css('opacity', 1); 
 
     $next.css('z-index', 210); 
 
     }, settings.transition + 100); 
 
     console.log(currentSlide, nextSlide); 
 
     currentSlide = ((currentSlide + 1) < children) ? (currentSlide + 1) : 0; 
 
     setTimeout(function() { 
 
     $container.showNext(); 
 
     }, settings.delay); 
 
    }; 
 
    setTimeout(function() { 
 
     $container.showNext(); 
 
    }, settings.delay); 
 
    }; 
 
}(jQuery); 
 

 
$.slideshow('.slideshow');
.slideshow-wrapper { 
 
     height: 100vh; 
 
     overflow: hidden; 
 
     position: relative; 
 
     width: 100%; 
 
    } 
 
    
 
    .slideshow { 
 
     height: 100%; 
 
     position: relative; 
 
     width: 100%; 
 
    } 
 
    
 
    .slide { 
 
     background-position: center; 
 
     background-size: cover; 
 
     height: 100%; 
 
     left: 0; 
 
     overflow: hidden; 
 
     position: absolute; 
 
     top: 0; 
 
     width: 100%; 
 
    }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> 
 
<div class="slideshow-wrapper"> 
 
    <div class="slideshow"> 
 
    <div class="slide" data-bg="https://s3.amazonaws.com/StartupStockPhotos/uploads/20160503/6.jpg"></div> 
 
    <div class="slide" data-bg="https://s3.amazonaws.com/StartupStockPhotos/uploads/20160503/5.jpg"></div> 
 
    <div class="slide" data-bg="https://s3.amazonaws.com/StartupStockPhotos/uploads/20160503/4.jpg"></div> 
 
    </div> 
 
</div>

回答

2

有在jQuery代码多个问题。以下是我发现的:

  1. 它正在运行竞态条件,其中JavaScript正在运行 之前比HTML有时间加载。尚未将最初的div 标签加载到文档对象中。容器div 的长度为0.带有0ms负载的单个setTimeout将解除阻塞,允许在JS运行之前加载HTML。
  2. 第3张图片(4.jpg)正在显示第1张,而不是第1张图片(6.jpg)。 z-index在代码中被更改,但没有被应用回图像。
  3. 的“当前”不透明度正在动画为0 &然后立刻被撞回升至1。我认为你在寻找改变的“下一个” 1的不透明度,而不是“现在”从1到0,然后回到1
  4. 初始化转换开始时顺利,但随后的重复动画往往会循环更快出现“下一个”图像之前&淡出到白色的页面。用户可能会发现,动画以6秒延迟&开始,然后加速至每张图像1/2秒。后面的动画太快了。
  5. 动画是弹出而不是溶解。这也不是使用交叉溶解,但我建议使用一个。我已经添加它来向你展示它是如何工作的。
  6. 的代码似乎并没有被清理,这就是为什么你正在运行到被迫使用$容器纠正编码问题进行的console.log &。容器变量作为参数传入(容器)之后,不能用“let container = ...”重新声明。当我通过传入一个“选择器”参数名来纠正这一点时,我可以删除容器变量上的$。这有助于区分哪些代码与jQuery &不符。
  7. 有在使用的setTimeout方法的严重依赖,但正如你可能已经知道......那些只运行1个&然后停止。为了使它们连续循环,setTimeout已经更改为setInterval。

试试这个edited JS Fiddle,它解决了这些问题。 顺便说一句,这里是jQuery .animate方法。

CSS变化:

  1. 增加了 “不透明度:0;”到所有幻灯片。
  2. 添加了“不透明度:1;”到第一张幻灯片。

CSS:

.slideshow-wrapper { 
    height: 100vh; 
    overflow: hidden; 
    position: relative; 
    width: 100%; 
} 

.slideshow { 
    height: 100%; 
    position: relative; 
    width: 100%; 
} 

.slide { 
    background-position: center; 
    background-size: cover; 
    height: 100%; 
    left: 0; 
    opacity: 0; /* <-- New --- */ 
    overflow: hidden; 
    position: absolute; 
    top: 0; 
    width: 100%; 
} 

.slide:first-child { /* <-- New --- */ 
    opacity: 1; 
} 

JavaScript有很多的编辑

!function($) { 
    "use strict"; 

    $.slideshow = function(selector) { 
     let container = $(selector); 
     let children = container.find('.slide').length; 

     container.find('.slide').each(function(index) { 
      let zIndex = 210 - index; 
      $(this).css('z-index', zIndex); // <-- This was missing, as it was loading the last image as the 1st image. 
      let bg = $(this).data('bg'); 
      $(this).css('background-image', 'url(' + bg + ')'); 
     }); 

     let settings = { 
      'delay': 2000 
     }; 

     let currentSlide = 0; 

     $.fn.showNext = function() { 
      let nextSlide = ((currentSlide + 1) < children) ? (currentSlide + 1) : 0; 
      let current = container.find('.slide:nth-child(' + (currentSlide + 1) + ')'); 
      let next = container.find('.slide:nth-child(' + (nextSlide + 1) + ')'); 

      next.animate({ 
      'opacity': 1, 
      'z-index': 210 
      }, settings.transition); 

      // Creates the Cross-Dissolve, as 1 image "next" is fadding up from opacity 0 to 1, while current is fadding down from 1 to 0. 
      current.animate({ 
      'opacity': 0, 
      'z-index': 200 
      }, settings.transition); 
     }; 

     // Starts the animation loop. 
     setInterval(function() { 
      container.showNext(); 
      currentSlide = ((currentSlide + 1) < children) ? (currentSlide + 1) : 0; 
     }, settings.delay); 
    }; 
}(jQuery); 

setTimeout(function() { 
    $.slideshow('.slideshow'); 
}, 0); // Fixes the race condition, by allowing the HTML to load before the JS runs. 

HTML的 - 使用的jsfiddle时没有变化,但删除脚本标签

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> 
<div class="slideshow-wrapper"> 
    <div class="slideshow"> 
    <div class="slide" data-bg="https://s3.amazonaws.com/StartupStockPhotos/uploads/20160503/6.jpg"></div> 
    <div class="slide" data-bg="https://s3.amazonaws.com/StartupStockPhotos/uploads/20160503/5.jpg"></div> 
    <div class="slide" data-bg="https://s3.amazonaws.com/StartupStockPhotos/uploads/20160503/4.jpg"></div> 
    </div> 
</div> 

玩得开心玩edited JS Fiddle进一步定制!

+0

我真的很感激你在深入观察我的代码。使用'setInteval'绝对是我想要的,而不是多个超时。我认为这里的代码片段的行为与我的实际产品有所不同,但是我最终做的是获取上一张图片,并使其z-索引低于队列中的下一个转换;他们是一样的,所以有时会显示错误的图像。非常感谢! –

+0

不客气!我以前遇到类似的幻灯片显示问题。很高兴今天能帮到你! – Clomp

+0

“它正处于竞争状态” - >由于其单线程特性,在Javascript中不可能出现竞争条件。您所描述的内容不是等待资源在执行之前可用,与在文件存在之前尝试打开文件,在安装之前浏览驱动器等等时会发生的情况相同。在这种情况下,应该避免使用'setTimeout()'方法,因为不能保证DOM将在下一次打勾时做好准备。你想把幻灯片初始化包装在'document.ready'事件中,就像这样:'$(function(){$ .slideshow('。slideshow');});'。 –

0

的主要问题就出在这里

setTimeout(function() { 
     $current.css('z-index', 200); 
     $current.css('opacity', 1); // this should be $next.css('opacity', 1); 
     $next.css('z-index', 210); 
     } 

你也应该尝试摆脱3的setTimeout(),他们看起来多余的。 您可以使用setInteval()更改图像。改变animate的完成回调中的CSS属性,你可以摆脱另一个setTimeout()。

检查:

!function($) { 
 
    "use strict"; 
 
    $.slideshow = function(container) { 
 
    let $container = $(container); 
 
    let children = $container.find('.slide').length; 
 
    $container.find('.slide').each(function(index) { 
 
     let zIndex = 210 - index; 
 
     let bg = $(this).data('bg'); 
 
     $(this).css('background-image', 'url(' + bg + ')'); 
 
    }); 
 
    let settings = { 
 
     'transition': 500, 
 
     'delay': 6000, 
 
    }; 
 
    let currentSlide = 0; 
 
    $.fn.showNext = function() { 
 
     let nextSlide = ((currentSlide + 1) < children) ? (currentSlide + 1) : 0; 
 
     let $current = $container.find('.slide:nth-child(' + (currentSlide + 1) + ')'); 
 
     let $next = $container.find('.slide:nth-child(' + (nextSlide + 1) + ')'); 
 
     $current.animate({ 
 
     'opacity': 0 
 
     }, settings.transition,function(){ 
 
     
 
     $current.css('z-index', 200); 
 
     $next.css('opacity', 1); 
 
     $next.css('z-index', 210); 
 
     
 
     }); 
 
     currentSlide = ((currentSlide + 1) < children) ? (currentSlide + 1) : 0; 
 
    }; 
 
    setInterval(function() { 
 
     $container.showNext(); 
 
    }, settings.delay); 
 
    }; 
 
}(jQuery); 
 

 
$.slideshow('.slideshow');
.slideshow-wrapper { 
 
     height: 100vh; 
 
     overflow: hidden; 
 
     position: relative; 
 
     width: 100%; 
 
    } 
 
    
 
    .slideshow { 
 
     height: 100%; 
 
     position: relative; 
 
     width: 100%; 
 
    } 
 
    
 
    .slide { 
 
     background-position: center; 
 
     background-size: cover; 
 
     height: 100%; 
 
     left: 0; 
 
     overflow: hidden; 
 
     position: absolute; 
 
     top: 0; 
 
     width: 100%; 
 
    }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> 
 
<div class="slideshow-wrapper"> 
 
    <div class="slideshow"> 
 
    <div class="slide" data-bg="https://s3.amazonaws.com/StartupStockPhotos/uploads/20160503/6.jpg"></div> 
 
    <div class="slide" data-bg="https://s3.amazonaws.com/StartupStockPhotos/uploads/20160503/5.jpg"></div> 
 
    <div class="slide" data-bg="https://s3.amazonaws.com/StartupStockPhotos/uploads/20160503/4.jpg"></div> 
 
    </div> 
 
</div>