如何在 css 中使用 @keyframes 交叉淡入淡出图片库?

Posted

技术标签:

【中文标题】如何在 css 中使用 @keyframes 交叉淡入淡出图片库?【英文标题】:How to use @keyframes for cross-fade gallery of images in css? 【发布时间】:2019-08-13 15:57:34 【问题描述】:

我有一个fiddle (Fiddle A),其中 2 张图像(2 个图块)发生交叉淡入淡出的图像库。这是我用过的html/css的sn-ps。

<div class="featured-block" style="display:flex; justify-content: center;">
  <a href="https://www.google.com/" class="featured-block__item cf">
    <div class="featured-block__item-inner">
      <figure class="featured-block__image img-fit" itemprop="image" itemscope="" itemtype="http://schema.org/ImageObject">
        <img class="default-opacity" src="https://i.imgur.com/EUqZ1Er.png" data-fallback-img="https://i.imgur.com/EUqZ1Er.png" >
      </figure>
    </div>
  </a>
</div>

这是我在上面的 html 中使用了 2 张图像(2 个图块)的 @keyframes:

@keyframes cf4FadeInOut 
    0% 
        opacity: 0;
    
    20% 
        opacity: 1;
        z-index: 999;
    
    33% 
        opacity: 1;
    
    53% 
        opacity: 0;
        z-index: 1;
    
    100% 
        opacity: 0;
    

Fiddle A 中的上述 css 动画在有 2 个图块(2 个图像)。

问题陈述:

上面的小提琴 (Fiddle A) 对于 2 张图像来说工作得非常好。我希望在有 3 和 4 个图像时发生相同的 css 动画/交叉淡入淡出图像库

这是 4 张图片(4 个图块)https://jsfiddle.net/zwjt8qko/1/embedded/result(小提琴 B)的小提琴

这是 3 张图片(3 个图块)https://jsfiddle.net/f6gr7kL1/embedded/result(小提琴 C)的小提琴

我想知道我应该在上面的 Fiddle B(4 张图片)和 Fiddle C(3 张图片)中的 关键帧中进行哪些更改,以便相同的 css-animation/cross-淡出 发生,这正在 Fiddle A 中发生。

我也对 javascript 解决方案持开放态度。

【问题讨论】:

您愿意接受 JavaScript 解决方案吗?最简单的方法是使用 JavaScript 来切换某个类,该类会使图像淡入并让所有其他类在失去该类时已经不可见或淡出。纯 CSS 解决方案是可能的,但会更复杂:您可能需要多个不同的 @keyframes 动画全部同步。 @cjl750 是的,我对 JS 解决方案持开放态度,但我希望它像 Fiddle A(有 2 个图像) 一样工作。我希望 3 张图片(小提琴 C)4 张图片(小提琴 B) 也发生同样的事情。 @cjl750 你在吗? 【参考方案1】:

JavaScript 方法

基本方法:

    在您的 CSS 中,所有图片默认为 opacity: 0。 在您的 HTML 中,为其中一张图片设置一个类名,将该图片的不透明度更改为 1。 在 JavaScript 中,定期在整个图片中切换该类。 甚至不用担心关键帧,直接在 JavaScript 中进行延迟。这让您可以更轻松地修改您希望脉冲动画的不同部分持续多长时间,而不必像使用关键帧那样计算animation-duration 总数的百分比。

const pics = document.querySelectorAll('.pic');
const lastPic = pics.length - 1;
const transitionDuration = 800; // matches CSS
const transitionDelay = 3000; // up to you
const totalDelay = transitionDuration + transitionDelay;
const intervalDelay = (transitionDuration * 2) + transitionDelay; // time to fade out + time to fade in + time to stay active

function toggleClass() 
  const activePic = document.querySelector('.pic.active');
  const activeIndex = Array.prototype.indexOf.call(pics, activePic);
  const nextIndex = activeIndex === lastPic ? 0 : activeIndex + 1;
  const nextPic = pics[nextIndex];

  setTimeout(() => activePic.classList.remove('active'), transitionDelay);
  setTimeout(() => nextPic.classList.add('active'), totalDelay);


setInterval(toggleClass, intervalDelay);
.wrapper 
  width: 400px;
  height: 300px;
  position: relative;

.pic 
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  opacity: 0;
  transition: opacity 800ms ease; /* immediately start fading out when active class is lost */

.pic.active 
  opacity: 1;
<div class="wrapper">
  <img class="pic active" src="https://via.placeholder.com/400x300?text=picture%201" >
  <img class="pic" src="https://via.placeholder.com/400x300?text=picture%202" >
  <img class="pic" src="https://via.placeholder.com/400x300?text=picture%203" >
  <img class="pic" src="https://via.placeholder.com/400x300?text=picture%204" >
</div>

关键帧方法

我不会在这里详细介绍,但它可能看起来像这样:

@keyframes pulse1 
  0% 
    opacity: 1;
  
  20% 
    opacity: 0;
  


@keyframes pulse2 
  0% 
    opacity: 0;
  
  25% 
    opacity: 1;
  
  45% 
    opacity: 0;
  


@keyframes pulse3 
  0% 
    opacity: 0;
  
  50% 
    opacity: 1;
  
  70% 
    opacity: 0;
  


@keyframes pulse4 
  0% 
    opacity: 0;
  
  75% 
    opacity: 1;
  

请注意,我们甚至不切换z-index,因为没有意义:一次只能看到其中一个。只需从一开始就将它们全部放在彼此之上,它们的z-index 就无关紧要了。

(我认为您在问题中的动画的z-index 部分甚至没有做任何事情,因为z-index 不是可动画的。)

【讨论】:

嗨,我将 JS 解决方案复制粘贴到 fiddle 中。我有一个简单的问题。我想知道有没有办法,我们可以放置active类包装类。此刻,我可以看到它带有img标签。 我之所以要求这样做是因为我不确定 div 中有多少图像,因为 div 中的图像是通过管理部分控制的。 @flash 你当然可以这样做。 JS 根本不需要在概念上进行修改,只需将类更改为适合您需要的任何内容。在您的情况下,您可能会使用document.querySelectorAll('.featured-block__item') 而不是document.querySelectorAll('.pic') 而不是active,而是使用featured-block__item-active @flash 您在这里遇到的一个问题是我直到现在才注意到您的图像都包含在链接中。好吧,opacity: 0 的东西仍然是可点击的,所以使用这种方法基本上无论 HTML 中的最后一个链接是什么,都会在顶部,因为我们没有切换 z-index,所以这将是总是被点击的链接。要解决这个问题,除了opacity: 1 之外,您可能还需要将z-index: 1 添加到活动类中。它不需要过渡;只要标志 A 淡出,标志 B 的链接就可以点击,即使它仍在忙于淡入。 谢谢。我标记为接受。在这个问题的基础上,我还有一个问题。一开始我想,我应该把它写在这里,但它会很多字,所以我会发布另一个问题。

以上是关于如何在 css 中使用 @keyframes 交叉淡入淡出图片库?的主要内容,如果未能解决你的问题,请参考以下文章

CSS:如何从函数中传递动画时间和`@keyframe`值?

@keyframe 动画后如何更改 css 属性?

如何在 MUI 中应用自定义动画效果@keyframes?

CSS @keyframes 光标动画在悬停时闪烁

CSS 动画总结

CSS3@keyframes规则和animation动画