React中如何使用(CSS)过渡动画实现背景图片切换时淡入淡出效果

5
我每3秒钟更改一个div的className(使用setInterval进行状态更改),每个className拥有不同的background-image。
我想在背景图片更改时使用transition css淡入淡出。我看到了一些更简单情况的示例,但我有超过两个元素需要更改/并且随着状态更改而更改图片。
我该如何做?
我已经上传了我的代码:https://stackblitz.com/edit/react-ubxffz,但我无法在此页面上上传图像,因此暂时将其替换为背景颜色。
这是Image Slide组件。
const imgUrls = [
    1,2,3
];

class ImageSlide extends Component {

render() {
    const { url } = this.props;
    const Text=...
    return (          
        <div>
            <div className={`pic${url}`}>
                <p className="p1_1">{Text.p1_1}</p>
            </div>
        </div>      
    );
}

这是一个App组件,它调用了ImageSlide组件。
class App extends Component {
constructor (props) {
    super(props);
        currentImageIndex: 0,
    };
}

// ...

componentDidMount() {
    this.interval = setInterval(() => {
        this.nextSlide(); //this function change the index state. 
        }, 3000);   
}

componentWillUnmount() {
clearInterval(this.interval);
}

// ...

<ImageSlide url={imgUrls[this.state.currentImageIndex]} />

这是针对每个类的CSS样式,用于设置背景图片。

.pic1 {
  background-image: url('images/img_01.png');
}

.pic2 {
  background-image: url('images/img_02.png');
}

.pic3 {
  background-image: url('images/img_03.png');
}

你可以在这里发布代码并向我们展示链接:https://stackblitz.com/edit/react-5zsqnt?file=index.js 谢谢! - לבני מלכה
谢谢。我已经上传到:https://stackblitz.com/edit/react-ubxffz。但是我无法在此页面上上传图片。 - 심시은
3个回答

3
这是它的工作原理:要使背景淡出,您需要有两个具有不同背景图像的元素,这些元素叠放在一起,然后进行交叉淡化。
stackblitz中的实现代码。
无框架的工作代码:

const imgUrls = [
    1,2,3
];
let currentIndex = 0;
const lastIndex = imgUrls.length - 1;

const nextSlide = () => {
  currentIndex++;
  currentIndex = currentIndex % (lastIndex + 1)
  
  // @See https://css-tricks.com/restart-css-animation/
  const elm = document.getElementById('root')
    .querySelector('[class^="pic"],[class*=" pix"]');
  elm.className = `pic${currentIndex+1}`
  const newone = elm.cloneNode(true);
  elm.parentNode.replaceChild(newone, elm);
}

interval = setInterval(() => {
  console.log()
  nextSlide(); //this function change the index state. 
}, 3000);
#root {
  position: relative;
  width: 640px;
  height: 480px;
}
#root .front,
#root .back {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}
#root .front {
  z-index: 2;
  opacity: 0;
}
#root .back {
  z-index: 1;
  opacity: 1;
}
#root [class^="pic"] .front,
#root [class*=" pic"] .front {
  -webkit-animation: in 3s 0s;
          animation: in 3s 0s;
}
#root .pic1 .front,
#root .pic2 .back {
  background-image: url("https://picsum.photos/640/480?image=1");
}
#root .pic1.init .back {
  background-image: none;
}
#root .pic2 .front,
#root .pic3 .back {
  background-image: url("https://picsum.photos/640/480?image=2");
}
#root .pic3 .front,
#root .pic1 .back {
  background-image: url("https://picsum.photos/640/480?image=3");
}

@-webkit-keyframes in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
<div id="root">
  <div class="pic1 init">
    <div class="front"></div>
    <div class="back"></div>
  </div>
</div>


该平台(stackexchange)上的所有代码均受知识共享许可证CC-BY SA 3.0许可证保护。 - yunzen
能否通过更改特定图像的显示方式来实现,而不是将两个图像叠放在一起并动画化它们的不透明度?假设我有3张图片,每3秒钟切换一次,非活动状态的图片将具有display:none。这种方法是否可行?@yunzen - ertemishakk
@ertemishakk,你不能通过动画来改变 display 属性。所以你想要的方式是不可能的。 - yunzen

2

将以下每个类别都使用animation

查看工作代码

加油!!

.pic1 {
  background-image: url('images/img_01.jpg');
  animation: fade 3s infinite;
}

.pic2 {
  background-image: url('images/img_02.jpg');
  animation: fade 3s infinite;
}

.pic3 {
  background-image: url('images/img_03.jpg');
   animation: fade 3s infinite;
}

@keyframes fade {
  0%,100% { opacity: 0 }
  50% { opacity: 1 }
}

0
我用 React Hooks 找到了解决方案。
import React, { useState, useEffect } from "react";

const heroImage = ["hero1.svg", "hero2.svg"];

export default function Home() {
  const [activeIndex, setactiveIndex] = useState(0);
  useEffect(() => {
    setInterval(() => {
      currentImageIndex === 0 ? setactiveIndex(1) : setactiveIndex(0);
    }, 3000);
  });

  return (
    <div>
      <img
        className={styles.featureImage}
        src={"img/" + heroImage[activeIndex]}
        alt={"imageTitle"}
      />
    </div>
  );
}

而CSS将会长成这样

.featureImage {
  height: 600px;
  width: 600px;
  animation: fade 3s infinite;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接