光滑的滑块 - css 过渡无限循环错误
slick slider - css transition infinite loop bug
我已经使用 slick slider 设置了一个滑块。使用下一个和上一个按钮时,项目会以漂亮的过渡进入视图。我遇到的问题是,当它重新开始其循环时,第一项 "snaps" 进入视图,而不是进行转换。此外,它似乎失去了内部索引,因为 css "odd" 和 "even" 类 已更改。请参阅下面的代码段:
$(document).ready(function() {
$('.items').slick({
slidesToShow: 2,
speed: 500
});
});
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
height: 150px;
}
.slick-list, .slick-track {
height: 100%;
}
ul li {
width: 350px;
height: 100%;
}
ul li .content {
width: 100%;
height: 100%;
transition: transform 0.5s linear;
text-align: center;
}
ul li .content span {
color: #fff;
font-size: 50px;
font-family: Arial;
position: relative;
top: 50%;
transform: translateY(-50%);
display: block;
}
ul li:nth-child(odd) .content {
background-color: red;
}
ul li:nth-child(even) .content {
background-color: green;
}
ul li:not(.slick-current) .content {
transform: scale(0.9);
}
<link href="https://cdn.jsdelivr.net/jquery.slick/1.6.0/slick.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.slick/1.6.0/slick.min.js"></script>
<ul class="items">
<li class="item">
<div class="content">
<span>1</span>
</div>
</li>
<li class="item">
<div class="content">
<span>2</span>
</div>
</li>
<li class="item">
<div class="content">
<span>3</span>
</div>
</li>
<li class="item">
<div class="content">
<span>4</span>
</div>
</li>
<li class="item">
<div class="content">
<span>5</span>
</div>
</li>
</ul>
我想我知道它为什么要这样做,因为它必须创建 "cloned" 项才能使无限循环功能正常工作。我尝试了几个不同的滑块插件,它们似乎都有类似的问题。
有谁知道我该如何解决这个问题? jsfiddle 在这里:https://jsfiddle.net/7kdmwkd9/1/
这不是问题,它是一项功能 - 这就是 slick 滑块(以及大多数其他无限循环滑块)的工作原理。基本上,如果滑块只克隆 div,它最终会出现巨大的性能问题,因此在某些地方 (beginning/end) 在动画之后它会重新渲染整个事情以重新开始。
如果您感兴趣,这里是滑块的概念验证,它基于转换并且不克隆任何东西,只是改变位置。也有可能用 order
实现同样的效果 - 没有尝试过但现在考虑了。
https://codepen.io/prowseed/pen/QMEQxg - 当然需要大量工作才能使其完全可用,但我尝试使其具有响应性并且与您的示例最相似。您只需要跟踪 add/remove 某些 类 的索引(例如 .current
)。
解决方案 1 - 使用 Flickity
如果你想尝试另一个轮播控件,你可以看看Flickity. According to my tests with the wrapAround option, it does not "snap" the first item back into position when the full cycle is complete; the transition goes on smoothly. You can see it at work in this jsfiddle。
至于根据项目 even/odd 索引格式化项目的问题,只有当项目数量为奇数时才会发生。一种解决方案是复制项目列表。取而代之
Item 1 / Item 2 / Item 3 / Item 4 / Item 5
你可以定义
Item 1 / Item 2 / Item 3 / Item 4 / Item 5 / Item 1 / Item 2 / Item 3 / Item 4 / Item 5
这将确保您处理的项目数量是偶数。
解决方案 2 - Slick Slider:添加过渡延迟
使用 Slick Slider,向过渡添加延迟有助于在循环完成时使其更平滑。在下面的代码片段中,我替换了:
ul li .content {
transition: transform 0.5s linear;
...
}
ul li:not(.slick-current) .content {
transform: scale(0.9);
}
和
ul li .content {
transition: transform 0.3s linear;
transition-delay: 0.5s;
...
}
ul li:not(.slick-current) .content {
transform: scale(0.9);
transition-delay: 0s;
}
$(document).ready(function() {
$('.items').slick({
infinite: true,
speed: 500,
slidesToShow: 2,
variableWidth: false
});
});
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
height: 150px;
}
.slick-list,
.slick-track {
height: 100%;
}
ul li {
width: 350px;
height: 100%;
}
ul li .content {
width: 100%;
height: 100%;
transition: transform 0.3s linear;
transition-delay: 0.5s;
text-align: center;
}
ul li .content span {
color: #fff;
font-size: 50px;
font-family: Arial;
position: relative;
top: 50%;
transform: translateY(-50%);
display: block;
}
ul li:nth-child(odd) .content {
background-color: red;
}
ul li:nth-child(even) .content {
background-color: green;
}
ul li:not(.slick-current) .content {
transform: scale(0.9);
transition-delay: 0s;
}
<link href="https://cdn.jsdelivr.net/jquery.slick/1.6.0/slick.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.slick/1.6.0/slick.min.js"></script>
<ul class="items">
<li class="item">
<div class="content">
<span>1</span>
</div>
</li>
<li class="item">
<div class="content">
<span>2</span>
</div>
</li>
<li class="item">
<div class="content">
<span>3</span>
</div>
</li>
<li class="item">
<div class="content">
<span>4</span>
</div>
</li>
<li class="item">
<div class="content">
<span>5</span>
</div>
</li>
<li class="item">
<div class="content">
<span>1</span>
</div>
</li>
<li class="item">
<div class="content">
<span>2</span>
</div>
</li>
<li class="item">
<div class="content">
<span>3</span>
</div>
</li>
<li class="item">
<div class="content">
<span>4</span>
</div>
</li>
<li class="item">
<div class="content">
<span>5</span>
</div>
</li>
</ul>
@GSTAR,最终你的代码没有错误,但是有一点css和你在使用slick时需要理解的js流程。
Slick 正在克隆您的幻灯片并在幻灯片的顶部和底部进行修改。如下所述。
Your Code before Slick implementation
<ul class="items">
<li class="item"><div class="content"><span>1</span></div></li>
<li class="item"><div class="content"><span>2</span></div></li>
<li class="item"><div class="content"><span>3</span></div></li>
<li class="item"><div class="content"><span>4</span></div></li>
<li class="item"><div class="content"><span>5</span></div></li>
<li class="item"><div class="content"><span>6</span></div></li>
</ul>
Your Code After Slick implementation
<ul class="items">
<li class="item slick-cloned"><div class="content"><span>4</span></div></li>
<li class="item slick-cloned"><div class="content"><span>5</span></div></li>
<li class="item slick-cloned"><div class="content"><span>6</span></div></li>
<li class="item"><div class="content"><span>1</span></div></li>
<li class="item"><div class="content"><span>2</span></div></li>
<li class="item"><div class="content"><span>3</span></div></li>
<li class="item"><div class="content"><span>4</span></div></li>
<li class="item"><div class="content"><span>5</span></div></li>
<li class="item"><div class="content"><span>6</span></div></li>
<li class="item slick-cloned"><div class="content"><span>1</span></div></li>
<li class="item slick-cloned"><div class="content"><span>2</span></div></li>
<li class="item slick-cloned"><div class="content"><span>3</span></div></li>
</ul>
此外,在添加此代码后,您的 animation
代码工作正常。但它不能在视觉上可见。如果你增加这个 animation
时间,它不会 snaps 你的浏览器。
如果您替换 javascript 代码,您就会知道发生了什么。
<script type="text/javascript">
$(document).ready(function() {
$('.items').slick({
centerMode:true,
slidesToShow: 3,
speed: 500,
infinite: true,
cssEase: 'linear',
variableWidth: true
});
});
</script>
因此在循环完成并到达执行的第一个幻灯片动画之后,在到达之前完成。
请检查下面我的代码段。
$(document).ready(function() {
$('.items').slick({
slidesToShow: 2,
speed: 500
});
});
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
height: 150px;
}
.slick-list, .slick-track {
height: 100%;
}
ul li {
width: 350px;
height: 100%;
}
ul li .content {
width: 100%;
height: 100%;
transition: transform 0.5s linear;
transition-delay: 0.5s;
text-align: center;
}
ul li .content span {
color: #fff;
font-size: 50px;
font-family: Arial;
position: relative;
top: 50%;
transform: translateY(-50%);
display: block;
}
ul li:nth-child(odd) .content {
background-color: red;
}
ul li:nth-child(even) .content {
background-color: green;
}
ul li:not(.slick-current) .content {
transform: scale(0.9);
}
<link href="https://cdn.jsdelivr.net/jquery.slick/1.6.0/slick.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.slick/1.6.0/slick.min.js"></script>
<ul class="items">
<li class="item">
<div class="content">
<span>1</span>
</div>
</li>
<li class="item">
<div class="content">
<span>2</span>
</div>
</li>
<li class="item">
<div class="content">
<span>3</span>
</div>
</li>
<li class="item">
<div class="content">
<span>4</span>
</div>
</li>
<li class="item">
<div class="content">
<span>5</span>
</div>
</li>
<li class="item">
<div class="content">
<span>6</span>
</div>
</li>
</ul>
在无限循环中,您有用户 odd
和 even
css,因此根据循环,您的下一张 first
幻灯片(克隆幻灯片)是绿色的,但您的原始幻灯片(第一张幻灯片)具有红色,因此它也闪烁颜色。如果您在 %2
中使用幻灯片数量,则不会发生这种情况。
希望它能帮助你更好地理解。
@Maciej Kwas
这可能是一项功能,但在本网站上,当您使用 "Center Mode" 查看滑块时它工作正常,从最后一张幻灯片滑动到第一张幻灯片时动画看起来不错。
http://kenwheeler.github.io/slick/
这是我的技巧 slick.js
警告!!小心使用它,导致它改变插件的源代码
1) 查找函数
Slick.prototype.setSlideClasses
并替换它的定义
来自
Slick.prototype.setSlideClasses = function(index)
到
Slick.prototype.setSlideClasses = function(index, oldSlide)
2) 在代码后的函数体中
_.$slides
.eq(index)
.addClass('slick-current');
添加
if(oldSlide!=undefined){
if(index==0 && oldSlide!=1){
var _current = this.$slides.eq(this.$slides.size()-1);
var __index = allSlides.index(_current);
var ss = allSlides.eq(__index+1);
ss.addClass('slick-current');
}
if(index==this.$slides.size()-1 && oldSlide!=this.$slides.size()-2){
var _current = this.$slides.eq(0);
var __index = allSlides.index(_current);
var ss = allSlides.eq(__index-1);
ss.addClass('slick-current');
}
}
3) 查找函数Slick.prototype.slideHandler
在它的正文中替换 call
oldSlide = _.currentSlide;
_.currentSlide = animSlide;
_.setSlideClasses(_.currentSlide);
至
oldSlide = _.currentSlide;
_.currentSlide = animSlide;
_.setSlideClasses(_.currentSlide,oldSlide);
Infinity 设置为 true,CenterMode 设置为 false
为电流添加效果
只是 css
/* slide when not active*/
.slick-slide[aria-hidden="true"]:not(.slick-cloned) ~ .slick-cloned[aria-hidden="true"] {
}
/* slide when active (when play last to first) */
.slick-slide[aria-hidden="true"]:not([tabindex="-1"]) + .slick-cloned[aria-hidden="true"] {
}
/* slide when active (when play first to last) */
.slick-slide[aria-hidden="true"] + .slick-cloned[aria-hidden="true"] {
}
我找到了一个非常简单的解决方案来解决我的问题版本,即一旦所有 4 张幻灯片都完成后,它会积极循环/错误。
我发现添加以下内容可提供无故障的无限循环
.slick-track {
transition: fade 2000ms ease-out;
infinite: true;
}
因为我很难放下过去,所以我仍在使用 Slick。我遇到了这个问题,结果发现问题是我的滑块图像使用了 srcset
属性。删除解决了问题。
我已经使用 slick slider 设置了一个滑块。使用下一个和上一个按钮时,项目会以漂亮的过渡进入视图。我遇到的问题是,当它重新开始其循环时,第一项 "snaps" 进入视图,而不是进行转换。此外,它似乎失去了内部索引,因为 css "odd" 和 "even" 类 已更改。请参阅下面的代码段:
$(document).ready(function() {
$('.items').slick({
slidesToShow: 2,
speed: 500
});
});
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
height: 150px;
}
.slick-list, .slick-track {
height: 100%;
}
ul li {
width: 350px;
height: 100%;
}
ul li .content {
width: 100%;
height: 100%;
transition: transform 0.5s linear;
text-align: center;
}
ul li .content span {
color: #fff;
font-size: 50px;
font-family: Arial;
position: relative;
top: 50%;
transform: translateY(-50%);
display: block;
}
ul li:nth-child(odd) .content {
background-color: red;
}
ul li:nth-child(even) .content {
background-color: green;
}
ul li:not(.slick-current) .content {
transform: scale(0.9);
}
<link href="https://cdn.jsdelivr.net/jquery.slick/1.6.0/slick.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.slick/1.6.0/slick.min.js"></script>
<ul class="items">
<li class="item">
<div class="content">
<span>1</span>
</div>
</li>
<li class="item">
<div class="content">
<span>2</span>
</div>
</li>
<li class="item">
<div class="content">
<span>3</span>
</div>
</li>
<li class="item">
<div class="content">
<span>4</span>
</div>
</li>
<li class="item">
<div class="content">
<span>5</span>
</div>
</li>
</ul>
我想我知道它为什么要这样做,因为它必须创建 "cloned" 项才能使无限循环功能正常工作。我尝试了几个不同的滑块插件,它们似乎都有类似的问题。
有谁知道我该如何解决这个问题? jsfiddle 在这里:https://jsfiddle.net/7kdmwkd9/1/
这不是问题,它是一项功能 - 这就是 slick 滑块(以及大多数其他无限循环滑块)的工作原理。基本上,如果滑块只克隆 div,它最终会出现巨大的性能问题,因此在某些地方 (beginning/end) 在动画之后它会重新渲染整个事情以重新开始。
如果您感兴趣,这里是滑块的概念验证,它基于转换并且不克隆任何东西,只是改变位置。也有可能用 order
实现同样的效果 - 没有尝试过但现在考虑了。
https://codepen.io/prowseed/pen/QMEQxg - 当然需要大量工作才能使其完全可用,但我尝试使其具有响应性并且与您的示例最相似。您只需要跟踪 add/remove 某些 类 的索引(例如 .current
)。
解决方案 1 - 使用 Flickity
如果你想尝试另一个轮播控件,你可以看看Flickity. According to my tests with the wrapAround option, it does not "snap" the first item back into position when the full cycle is complete; the transition goes on smoothly. You can see it at work in this jsfiddle。
至于根据项目 even/odd 索引格式化项目的问题,只有当项目数量为奇数时才会发生。一种解决方案是复制项目列表。取而代之
Item 1 / Item 2 / Item 3 / Item 4 / Item 5
你可以定义
Item 1 / Item 2 / Item 3 / Item 4 / Item 5 / Item 1 / Item 2 / Item 3 / Item 4 / Item 5
这将确保您处理的项目数量是偶数。
解决方案 2 - Slick Slider:添加过渡延迟
使用 Slick Slider,向过渡添加延迟有助于在循环完成时使其更平滑。在下面的代码片段中,我替换了:
ul li .content {
transition: transform 0.5s linear;
...
}
ul li:not(.slick-current) .content {
transform: scale(0.9);
}
和
ul li .content {
transition: transform 0.3s linear;
transition-delay: 0.5s;
...
}
ul li:not(.slick-current) .content {
transform: scale(0.9);
transition-delay: 0s;
}
$(document).ready(function() {
$('.items').slick({
infinite: true,
speed: 500,
slidesToShow: 2,
variableWidth: false
});
});
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
height: 150px;
}
.slick-list,
.slick-track {
height: 100%;
}
ul li {
width: 350px;
height: 100%;
}
ul li .content {
width: 100%;
height: 100%;
transition: transform 0.3s linear;
transition-delay: 0.5s;
text-align: center;
}
ul li .content span {
color: #fff;
font-size: 50px;
font-family: Arial;
position: relative;
top: 50%;
transform: translateY(-50%);
display: block;
}
ul li:nth-child(odd) .content {
background-color: red;
}
ul li:nth-child(even) .content {
background-color: green;
}
ul li:not(.slick-current) .content {
transform: scale(0.9);
transition-delay: 0s;
}
<link href="https://cdn.jsdelivr.net/jquery.slick/1.6.0/slick.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.slick/1.6.0/slick.min.js"></script>
<ul class="items">
<li class="item">
<div class="content">
<span>1</span>
</div>
</li>
<li class="item">
<div class="content">
<span>2</span>
</div>
</li>
<li class="item">
<div class="content">
<span>3</span>
</div>
</li>
<li class="item">
<div class="content">
<span>4</span>
</div>
</li>
<li class="item">
<div class="content">
<span>5</span>
</div>
</li>
<li class="item">
<div class="content">
<span>1</span>
</div>
</li>
<li class="item">
<div class="content">
<span>2</span>
</div>
</li>
<li class="item">
<div class="content">
<span>3</span>
</div>
</li>
<li class="item">
<div class="content">
<span>4</span>
</div>
</li>
<li class="item">
<div class="content">
<span>5</span>
</div>
</li>
</ul>
@GSTAR,最终你的代码没有错误,但是有一点css和你在使用slick时需要理解的js流程。
Slick 正在克隆您的幻灯片并在幻灯片的顶部和底部进行修改。如下所述。
Your Code before Slick implementation
<ul class="items">
<li class="item"><div class="content"><span>1</span></div></li>
<li class="item"><div class="content"><span>2</span></div></li>
<li class="item"><div class="content"><span>3</span></div></li>
<li class="item"><div class="content"><span>4</span></div></li>
<li class="item"><div class="content"><span>5</span></div></li>
<li class="item"><div class="content"><span>6</span></div></li>
</ul>
Your Code After Slick implementation
<ul class="items">
<li class="item slick-cloned"><div class="content"><span>4</span></div></li>
<li class="item slick-cloned"><div class="content"><span>5</span></div></li>
<li class="item slick-cloned"><div class="content"><span>6</span></div></li>
<li class="item"><div class="content"><span>1</span></div></li>
<li class="item"><div class="content"><span>2</span></div></li>
<li class="item"><div class="content"><span>3</span></div></li>
<li class="item"><div class="content"><span>4</span></div></li>
<li class="item"><div class="content"><span>5</span></div></li>
<li class="item"><div class="content"><span>6</span></div></li>
<li class="item slick-cloned"><div class="content"><span>1</span></div></li>
<li class="item slick-cloned"><div class="content"><span>2</span></div></li>
<li class="item slick-cloned"><div class="content"><span>3</span></div></li>
</ul>
此外,在添加此代码后,您的 animation
代码工作正常。但它不能在视觉上可见。如果你增加这个 animation
时间,它不会 snaps 你的浏览器。
如果您替换 javascript 代码,您就会知道发生了什么。
<script type="text/javascript">
$(document).ready(function() {
$('.items').slick({
centerMode:true,
slidesToShow: 3,
speed: 500,
infinite: true,
cssEase: 'linear',
variableWidth: true
});
});
</script>
因此在循环完成并到达执行的第一个幻灯片动画之后,在到达之前完成。
请检查下面我的代码段。
$(document).ready(function() {
$('.items').slick({
slidesToShow: 2,
speed: 500
});
});
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
height: 150px;
}
.slick-list, .slick-track {
height: 100%;
}
ul li {
width: 350px;
height: 100%;
}
ul li .content {
width: 100%;
height: 100%;
transition: transform 0.5s linear;
transition-delay: 0.5s;
text-align: center;
}
ul li .content span {
color: #fff;
font-size: 50px;
font-family: Arial;
position: relative;
top: 50%;
transform: translateY(-50%);
display: block;
}
ul li:nth-child(odd) .content {
background-color: red;
}
ul li:nth-child(even) .content {
background-color: green;
}
ul li:not(.slick-current) .content {
transform: scale(0.9);
}
<link href="https://cdn.jsdelivr.net/jquery.slick/1.6.0/slick.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.slick/1.6.0/slick.min.js"></script>
<ul class="items">
<li class="item">
<div class="content">
<span>1</span>
</div>
</li>
<li class="item">
<div class="content">
<span>2</span>
</div>
</li>
<li class="item">
<div class="content">
<span>3</span>
</div>
</li>
<li class="item">
<div class="content">
<span>4</span>
</div>
</li>
<li class="item">
<div class="content">
<span>5</span>
</div>
</li>
<li class="item">
<div class="content">
<span>6</span>
</div>
</li>
</ul>
在无限循环中,您有用户 odd
和 even
css,因此根据循环,您的下一张 first
幻灯片(克隆幻灯片)是绿色的,但您的原始幻灯片(第一张幻灯片)具有红色,因此它也闪烁颜色。如果您在 %2
中使用幻灯片数量,则不会发生这种情况。
希望它能帮助你更好地理解。
@Maciej Kwas
这可能是一项功能,但在本网站上,当您使用 "Center Mode" 查看滑块时它工作正常,从最后一张幻灯片滑动到第一张幻灯片时动画看起来不错。 http://kenwheeler.github.io/slick/
这是我的技巧 slick.js 警告!!小心使用它,导致它改变插件的源代码
1) 查找函数
Slick.prototype.setSlideClasses
并替换它的定义
来自
Slick.prototype.setSlideClasses = function(index)
到
Slick.prototype.setSlideClasses = function(index, oldSlide)
2) 在代码后的函数体中
_.$slides
.eq(index)
.addClass('slick-current');
添加
if(oldSlide!=undefined){
if(index==0 && oldSlide!=1){
var _current = this.$slides.eq(this.$slides.size()-1);
var __index = allSlides.index(_current);
var ss = allSlides.eq(__index+1);
ss.addClass('slick-current');
}
if(index==this.$slides.size()-1 && oldSlide!=this.$slides.size()-2){
var _current = this.$slides.eq(0);
var __index = allSlides.index(_current);
var ss = allSlides.eq(__index-1);
ss.addClass('slick-current');
}
}
3) 查找函数Slick.prototype.slideHandler 在它的正文中替换 call
oldSlide = _.currentSlide;
_.currentSlide = animSlide;
_.setSlideClasses(_.currentSlide);
至
oldSlide = _.currentSlide;
_.currentSlide = animSlide;
_.setSlideClasses(_.currentSlide,oldSlide);
Infinity 设置为 true,CenterMode 设置为 false 为电流添加效果 只是 css
/* slide when not active*/
.slick-slide[aria-hidden="true"]:not(.slick-cloned) ~ .slick-cloned[aria-hidden="true"] {
}
/* slide when active (when play last to first) */
.slick-slide[aria-hidden="true"]:not([tabindex="-1"]) + .slick-cloned[aria-hidden="true"] {
}
/* slide when active (when play first to last) */
.slick-slide[aria-hidden="true"] + .slick-cloned[aria-hidden="true"] {
}
我找到了一个非常简单的解决方案来解决我的问题版本,即一旦所有 4 张幻灯片都完成后,它会积极循环/错误。
我发现添加以下内容可提供无故障的无限循环
.slick-track {
transition: fade 2000ms ease-out;
infinite: true;
}
因为我很难放下过去,所以我仍在使用 Slick。我遇到了这个问题,结果发现问题是我的滑块图像使用了 srcset
属性。删除解决了问题。