具有 ken-burns-out 图像跳转错误的 Slick Slider

Slick Slider with ken-burns-out image jumps bug

幻灯片动画(scale(1.3) 到 scale(1))结束并返回幻灯片后,我遇到了这个烦人的跳跃。

我希望每张活动幻灯片都已经按比例 (1.3) 进行缩放。

  $('.home-slider').slick({
     slidesToScroll: 1,
        slidesToShow: 1,
        //arrows: true,
        autoplay: true,
        autoplaySpeed: 7000,
        dots: false
  })
body,
html {
  height: 100%;
  background: #333;
  font-family: 'Roboto', sans-serif;
}

.slideshow {
  position: relative;
  z-index: 1;
  height: 100%;
  max-width: 700px;
  margin: 50px auto;
}

.slideshow .item {
  height: 100%;
  position: relative;
  z-index: 1;
}
.slideshow .item img {
  width: 100%;
  
}
.slideshow .item.slick-active img {
  -webkit-animation: ken-burns-out 8s 1 ease-in-out forwards;
  animation: ken-burns-out 8s 1 ease-in-out forwards;
}


/*//The animation: from 1.3 scale to 1*/
@-webkit-keyframes ken-burns-out {
    0% {
        -webkit-transform: scale(1.3);
        transform: scale(1.3)
    }

    to {
        -webkit-transform: scale(1);
        transform: scale(1)
    }
}

@keyframes ken-burns-out {
    0% {
        -webkit-transform: scale(1.3);
        transform: scale(1.3)
    }

    to {
        -webkit-transform: scale(1);
        transform: scale(1)
    }
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick-theme.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.3/jquery.easing.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick.min.js"></script>





<div class="slideshow">
  <div class="home-slider">
    <div class="item">
      <img src="https://images.unsplash.com/photo-1532386236358-a33d8a9434e3?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=978&q=80" />
    </div>
    <div class="item">
      <img src="https://images.unsplash.com/photo-1518791841217-8f162f1e1131?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80" />
    </div>
  </div>
</div>

问题的发生是因为所有图像都变得相同 z-index。

当您从第一张幻灯片导航到最后一张幻灯片(向右滑动)时,我的代码不起作用,但它是开始的东西。

首先,从这个选择器中删除 z-index:.slideshow .item

然后,向每张图片添加变换,以便每张图片都以此比例开始(可以向每张图片添加 class 名称,然后更改选择器):

img {
  transform: scale(1.3);
}

添加一个函数以通过索引获取 slicks(有克隆的 slicks 元素,所以我使用获取 un-cloned slicks 的选择器):

function getSlickByIndex(index) {
  return $('.item:not(.slick-cloned)[data-slick-index="' + index + '"]');
}

然后,添加 init 事件(逻辑使第一张幻灯片获得更大的 zIndex=1 他所有具有 zIndex=0 的兄弟姐妹),以及 beforeChange(逻辑使下一个 slick 获得更大的索引,其他的获得更小的索引):

$('.home-slider').on('init', function(event, slick){
  getSlickByIndex(0).css('zIndex', '1');
}).on('beforeChange', function(event, slick, currentSlide, nextSlide){
  getSlickByIndex(currentSlide).css('zIndex', '0');
  getSlickByIndex(nextSlide).css('zIndex', '1');
});

演示

img {
  transform: scale(1.3);
}

body,
html {
  height: 100%;
  background: #333;
  font-family: 'Roboto', sans-serif;
}

.slideshow {
  position: relative;
  z-index: 1;
  height: 100%;
  max-width: 700px;
  margin: 50px auto;
}

.slideshow .item {
  height: 100%;
  position: relative;
  z-index: 1;
}
.slideshow .item img {
  width: 100%;
  
}
.slideshow .item.slick-active img {
  -webkit-animation: ken-burns-out 8s 1 ease-in-out forwards;
  animation: ken-burns-out 8s 1 ease-in-out forwards;
}


/*//The animation: from 1.3 scale to 1*/
@-webkit-keyframes ken-burns-out {
    0% {
        -webkit-transform: scale(1.3);
        transform: scale(1.3)
    }

    to {
        -webkit-transform: scale(1);
        transform: scale(1)
    }
}

@keyframes ken-burns-out {
    0% {
        -webkit-transform: scale(1.3);
        transform: scale(1.3)
    }

    to {
        -webkit-transform: scale(1);
        transform: scale(1)
    }
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.3/jquery.easing.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick.min.js"></script>





<div class="slideshow">
  <div class="home-slider">
    <div class="item">
      <img src="https://images.unsplash.com/photo-1532386236358-a33d8a9434e3?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=978&q=80" />
    </div>
    <div class="item">
      <img src="https://images.unsplash.com/photo-1518791841217-8f162f1e1131?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80" />
    </div>
    <div class="item">
      <img src="https://images.unsplash.com/photo-1532386236358-a33d8a9434e3?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=978&q=80" />
    </div>
    <div class="item">
      <img src="https://images.unsplash.com/photo-1518791841217-8f162f1e1131?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80" />
    </div>
  </div>
</div>

<script>

  function getSlickByIndex(index) {
    return $('.item:not(.slick-cloned)[data-slick-index="' + index + '"]');
  }
  
$('.home-slider').on('init', function(event, slick){
  getSlickByIndex(0).css('zIndex', '5555');
}).on('beforeChange', function(event, slick, currentSlide, nextSlide){
  getSlickByIndex(currentSlide).css('zIndex', '0');
  getSlickByIndex(nextSlide).css('zIndex', '5555');
  
  
});
    $('.home-slider').slick({
     slidesToScroll: 1,
        slidesToShow: 1,
       
        //arrows: true,
        autoplay: true,
        autoplaySpeed: 7000,
        dots: false
  });

</script>

这是有效的 fiddle:https://codepen.io/alonsh/pen/JQmZjj

您的图像从 1 的比例开始,然后当它们变为活动状态时,动画从 1.3 处开始,这就是导致跳跃的原因。您需要做的是通过将此添加到 .item img css 定义来从 scale(1.3) 开始所有图像。 只这样做会导致图像溢出到另一个图像上。为了解决这个问题,通过添加 overflow: hidden 确保每个 .item 的内容不会溢出,这会导致:

编辑

这导致代码仍然无法正常工作。我们仍然需要上一个答案的所有内容,但我们最终遇到了相反的问题,即图像在关闭时跳转到完全缩放的大小。

这有点像兔子洞,但是 css 中有一个 animation-play-state 属性,我们可以用它来暂停动画item 变为非活动状态,所以我让动画在每个 .item 元素上播放,这意味着当它滚动离开并且活动 class 丢失时,它将在原处暂停动画。

这几乎让我们得到了想要的结果,但是当图像重新进入视图时,它会从中断的地方继续。事实证明,没有一种很好的方法可以让 css 动画重新启动,所以我正在做的是我已经绑定到 slick 的幻灯片更改事件,当幻灯片发生更改时(我相信保证只有活动幻灯片可见)我重置了 .item 动画。为了以不中断活动幻灯片的方式执行此操作,我添加了一个 class .animated,我可以删除它,然后稍后在 setTimeout 中添加回来。需要延迟才能重新启动动画。

你希望这就是结局,但你错了。然后 Slick 认为开始滑动,然后返回到同一图像上是幻灯片更改 ("change") 所以我添加了一个当前幻灯片变量来跟踪我们在哪张幻灯片上并且只重置 .animated class 如果幻灯片确实发生了变化。 重要说明: 在实际项目中,我会将此 currentSlide 包装在某种 class/object 中以跟踪单个幻灯片的状态,因为就目前而言,您不能在一个页面上放映多个幻灯片而不会受到干扰。但我不打算为了一个简单的例子而写下所有这些。

所有这一切之后,我们最终得到了略有不同的 CSS 和更多的 JS 以获得工作结果:

$('.home-slider').slick({
  slidesToScroll: 1,
  slidesToShow: 1,
  //arrows: true,
  autoplay: true,
  autoplaySpeed: 7000,
  dots: false
});
var currentSlide = 0;
$('.home-slider').on('afterChange', function(event, slick, newSlide){
  var items = $('.home-slider .item');
  if(currentSlide != newSlide){
    currentSlide = newSlide;
    items.removeClass('animated');
    setTimeout(function(){
      items.addClass('animated');
    });
  }
});
body,
html {
  height: 100%;
  background: #333;
  font-family: 'Roboto', sans-serif;
}

.slideshow {
  position: relative;
  z-index: 1;
  height: 100%;
  max-width: 700px;
  margin: 50px auto;
}

.slideshow .item {
  height: 100%;
  position: relative;
  overflow: hidden;
}
.slideshow .item img {
  width: 100%;
  -webkit-transform: scale(1.3);
  transform: scale(1.3);
}
.slideshow .item.animated img {
  -webkit-animation: ken-burns-out 8s 1 ease-in-out forwards;
  animation: ken-burns-out 8s 1 ease-in-out forwards;
  animation-play-state: paused;
}
.slideshow .item.slick-active img {
  animation-play-state: running;
}


/*//The animation: from 1.3 scale to 1*/
@-webkit-keyframes ken-burns-out {
    0% {
        -webkit-transform: scale(1.3);
        transform: scale(1.3);
    }

    to {
        -webkit-transform: scale(1);
        transform: scale(1)
    }
}

@keyframes ken-burns-out {
    0% {
        -webkit-transform: scale(1.3);
        transform: scale(1.3)
    }

    to {
        -webkit-transform: scale(1);
        transform: scale(1)
    }
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick-theme.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.3/jquery.easing.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick.min.js"></script>





<div class="slideshow">
  <div class="home-slider">
<div class="item animated">
  <img src="https://images.unsplash.com/photo-1532386236358-a33d8a9434e3?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=978&q=80" />
</div>
<div class="item animated">
  <img src="https://images.unsplash.com/photo-1518791841217-8f162f1e1131?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80" />
</div>
  </div>
</div>