盖茨比图片之间的淡入淡出

时间:2018-09-11 17:24:09

标签: javascript reactjs image css-transitions gatsby

对于gatsby图像,我使用setInterval()交换了一些照片并更改了src,就像这样:

componentDidMount() {
  this.setState({
    intervalFunction: setInterval(this.imageCycle, 10000),
  });
}

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

imageCycle() {
   let newImage = this.state.equiptmentCurrent + 1;
   if (newImage >= this.state.equiptmentImages.length) {
    newImage = 0;
   }
   this.setState(state => ({
     equiptmentCurrent: newImage,
   }));
}

渲染方法:

 <IMG
   sizes={this.state.equiptmentImages[this.state.equiptmentCurrent]}
   outerWrapperClassName="coverOuter"
   position="absolute"
   style={gatsbyImgStyle}
 />

当源更改时,是否有任何方法可以对此进行过渡?

2 个答案:

答案 0 :(得分:0)

这是一种可能的方法:

  1. 通过position: absolute在彼此之间堆叠两个标签
  2. 使用transition: opacity 1s ease-in-out;
  3. 为其设置样式
  4. 在此状态上放置一个新的showFront: true属性。
  5. 在componentDidMount间隔钩上:
    1. 为不活动的组件更新下一个图像大小(通过状态obj)。
    2. 根据showFront的值在每个组件上分别添加1和0的不透明度。您可以有条件地添加带有以下内容的新类:className={"my-image-class " + (this.state.showFront ? 'seen' : 'not-seen')}(底部图像则相反)。在样式化组件中,可以通过将showFront作为prop来实现。
  6. 通过componentDidMount setInterval挂钩切换showFront。

答案 1 :(得分:0)

这是我的CrossFadeImage实现。它与img类似,不同之处在于它可以在检测到props.src更改时为您处理动画,并具有用于自定义过渡的额外道具

enter image description here

import React from "react";

const usePrevious = <T extends any>(value: T) => {
  const ref = React.useRef<T>();
  React.useEffect(() => {
    ref.current = value;
  }, [value]);
  return ref.current;
};
const useRequestAnimationFrame = (): [(cb: () => void) => void, Function] => {
  const handles = React.useRef<number[]>([]);
  const _raf = (cb: () => void) => {
    handles.current.push(requestAnimationFrame(cb));
  };
  const _resetRaf = () => {
    handles.current.forEach((id) => cancelAnimationFrame(id));
    handles.current = [];
  };

  return [_raf, _resetRaf];
};

type ImageProps = {
  src: string;
  alt?: string;
  transitionDuration?: number;
  curve?: string;
};

const CrossFadeImage = (props: ImageProps) => {
  const { src, alt, transitionDuration = 0.35, curve = "ease" } = props;
  const oldSrc = usePrevious(src);
  const [topSrc, setTopSrc] = React.useState<string>(src);
  const [bottomSrc, setBottomSrc] = React.useState<string>("");
  const [bottomOpacity, setBottomOpacity] = React.useState(0);
  const [display, setDisplay] = React.useState(false);
  const [raf, resetRaf] = useRequestAnimationFrame();

  React.useEffect(() => {
    if (src !== oldSrc) {
      resetRaf();
      setTopSrc("");
      setBottomSrc("");

      raf(() => {
        setTopSrc(src);
        setBottomSrc(oldSrc!);
        setBottomOpacity(99);

        raf(() => {
          setBottomOpacity(0);
        });
      });
    }
  });

  return (
    <div
      className="imgContainer"
      style={{
        position: "relative",
        height: "100%"
      }}
    >
      {topSrc && (
        <img
          style={{
            position: "absolute",
            opacity: display ? "100%" : 0,
            transition: `opacity ${transitionDuration}s ${curve}`
          }}
          onLoad={() => setDisplay(true)}
          src={topSrc}
          alt={alt}
        />
      )}
      {bottomSrc && (
        <img
          style={{
            position: "absolute",
            opacity: bottomOpacity + "%",
            transition: `opacity ${transitionDuration}s ${curve}`
          }}
          src={bottomSrc}
          alt={alt}
        />
      )}
    </div>
  );
};

export default CrossFadeImage;

实时演示

Edit demo app on CodeSandbox