javascript - react : Trying to achieve a sequential fade-in effect with a Masonry layout but it's out of order

标签 javascript html css reactjs

我一直在尝试制作一个具有连续淡入效果的 Masonry 画廊,以便图片一张一张地淡入。还有一个随机播放功能,可以使图像随机化,并且在随机播放后它们会再次淡入。

这是演示和代码:

https://tuo1t.csb.app/

https://codesandbox.io/s/objective-swartz-tuo1t

第一次访问页面时,动画是正确的。然而一旦我们点击了随机播放按钮,奇怪的事情发生了:经常有一些图片在淡入之前的图像之后并没有依次淡入,甚至没有淡入动画,它们只是从订单。

我实现这个动画的方法是根据图像的索引添加一个延迟过渡,并使用 ref 来跟踪图像。

首先我初始化ref

 let refs = {};
  for (let i = 0; i < images.length; i++) {
    refs[i] = useRef(null);
  }

然后我渲染图库

 <Mansory gap={"1em"} minWidth={minWidth}>
        {imgs.map((img, i) => {
          return (
            <PicContainer
              index={img.index}
              selected={isSelected}
              key={img.index}
            >
              <Enlarger
                src={img.url}
                index={img.index}
                setIsSelected={setIsSelected}
                onLoad={() => {
                  refs[i].current.toggleOpacity(1); <--- start with zero opacity images till those are loaded
                }}
                ref={refs[i]}
                realIndex={i}
              />
            </PicContainer>
          );
        })}
      </Mansory>

对于每个图像组件

class ZoomImg extends React.Component {
  state = { zoomed: false, opacity: 0 };

  toggleOpacity = o => {
    console.log("here");
    this.setState({ opacity: o }); <-- a setter function to change the opacity state via refs:
  };

  render() {
    const {
      realIndex,
      index,
      src,
      enlargedSrc,
      setIsSelected,
      onLoad
    } = this.props;
    return (
      <div style={{ margin: "0.25rem" }} onLoad={onLoad}>
        <Image
          style={{
            opacity: this.state.opacity,
            transition: "opacity 0.5s cubic-bezier(0.25,0.46,0.45,0.94)",
            transitionDelay: `${realIndex * 0.1}s` <--- add a delay transition based on the index of the image.
          }}
          zoomed={this.state.zoomed}
          src={src}
          enlargedSrc={enlargedSrc}
          onClick={() => {
            this.setState({ zoomed: true });
            setIsSelected(index);
          }}
          onRequestClose={() => {
            this.setState({ zoomed: false });
            setIsSelected(null);
          }}
          renderLoading={
            <div
              style={{
                position: "absolute",
                top: "50%",
                color: "white",
                left: "50%",
                transform: "translateY(-50%} translateX(-50%)"
              }}
            >
              Loading!
            </div>
          }
        />
      </div>
    );
  }
}

我在 setter 函数中使用了 console.log("here");,它将被调用以通过 refs 更改不透明度状态。有16张图片,所以最初调用了16次。但是当我点击随机播放按钮时,你可以看到它被调用了 少于 16 次,因为有些图片没有淡入就直接显示了。

我已经为这个问题苦苦挣扎了好几天,真的希望有人能给我一些提示。

最佳答案

问题是您在 shuffle 方法中只添加了一些新图像,一种方法是首先将 0 不透明度应用于所有 refs,然后等待几毫秒再次添加 1 不透明度,如 here .

但是,我会推荐一种更好的动画方法,我喜欢 shifty及其 Tweenable 模块。

关于javascript - react : Trying to achieve a sequential fade-in effect with a Masonry layout but it's out of order,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57671489/

相关文章:

javascript - 在 header 中显示 id 属性

html - 具有行扩展的 PrimeNG 数据表调用新服务并连续显示数据 Angular 5

javascript - 我们可以使用 jquery 将选择从一个页面转移到另一个页面吗

html - Bootstrap 4 中带有单选按钮的内衬标签

javascript - undefined === undefined 比较什么?

javascript - react 路由器 : nested resources

javascript - javascript 的 func_get_args

javascript - dojo/dijit ContentPane 设置内容

javascript - 写一个 jQuery 选择器来过滤没有子类的子 div

javascript - 滚动条中包含的选项卡名称