每当 <img src={value} /> src 值改变时触发动画

trigger animation whenever the <img src={value} /> src value changes

我正在使用 React 创建一个 img 元素,该元素在特定时间后使用 setInterval 函数根据包含许多图像的数组更改其 src 属性。

所以我想在 src 属性发生变化时制作动画,我正在考虑使用 React.useEffect() 钩子来观察 src 变化并添加一些动画但是我无法在逻辑上更进一步。

我的代码:

import Canada from "../images/Canada.jpg"
import Tokyo from "../images/Tokyo.jpg"
import NewYork from "../images/NewYork.jpg"
import southKorea from "../images/southKorea.jpg"


function AboutMe() {

    const imgArray = [NewYork, Tokyo, Canada, southKorea]
     let i = 0;
    const maxImgArray = imgArray.length -1 ;
    const swap = function() {
        let image = imgArray[i];
        i = (i === maxImgArray) ? 0 : ++i;
        const attr = document.getElementById("moving-image");
        attr.src=image;
    }
    setInterval(swap, 5000)
    return (
    <section className="About-me">
        <h1>About me</h1>
        <div className="container">
        <div className="cities-images">
            <img 
            src={Tokyo}
            alt="NewYork" id="moving-image"></img>
            <label class="switch">
              <input type="checkbox"/>
              <span class="slider round"></span>
            </label>
        </div>
            <div className="info">
                
            </div>
        </div>
    </section>    
    )
}

通过在 React 中使用 useState 钩子,我们可以 re-render 具有更新值的组件。所以对于src的改变,我们可以使用useState来更新图片的当前src。

通过使用 useEffect 钩子,我们可以在 src 状态改变后做任何事情,比如设置不同的动画。

组件状态

  const [image, setImage] = useState(Usa);
  const [imageIndex, setImageIndex] = useState(0);
  const imgArray = [Usa, Japan, Canada, SouthKorea];

useEffect

useEffect(() => {
let interval = null;
if (i !== maxImgArray) {
  interval = setInterval(() => {
    let image = imgArray[imageIndex];
    const attr = document.getElementById("moving-image");
    attr.src = image;
    // update the img index to state
    setImageIndex((imageIndex) =>
      imageIndex === maxImgArray ? 0 : imageIndex + 1
    );
    // update the src in state.
    setImage(attr.src);
  }, 3000);
}
// When our code runs and reruns for every render, useEffect also cleans up after itself using the cleanup function.
// Here we clear the interval to remove the effects that could happen with state change while interval.
return () => clearInterval(interval);
}, [image, imageIndex]); // when image, imageIndex gets change, useEffect will be triggered.

组件这里我用了framer-motion做动画

<section className="Country-flag">
    <h1>Country Flag</h1>
    <div className="container">
      <motion.div
        key={image}
        animate={{ x: 100, opacity: 1 }}
        transition={{
          delay: 1,
          x: { type: "spring", stiffness: 100 },
          default: { duration: 2 }
        }}
      >
        {/* when state {image} value change, this component will re-render with new src */}
        <img alt="NewYork" src={image} id="moving-image"></img>
      </motion.div>
      <div className="info"></div>
    </div>
  </section>

检查此示例 sandbox 以获取生成的代码。

如果您希望每个 img 有不同的动画,则为动画添加另一个状态变量,并为每个图像状态更改 useEffect 中的值。