简体   繁体   中英

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

I been trying to make a Masonry gallery with a sequential fade-in effect so that the pictures fade in one by one. And there is also a shuffle feature which will randomize the images and they fade in again after being shuffled.

here is the demo and the code:

https://tuo1t.csb.app/

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

When first visiting the page, the animation is correct. However once we click on the shuffle button, something weird happened: There are often some pictures don't fade-in sequentially after the image before them faded in, there is even no fade-in animation on them, they just show up out of order.

The way I achieved this animation is by adding a delay transition based on the index of the image, and use ref to track images.

first I initialize the ref

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

and I render the gallery

 <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>

for the every image component

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>
    );
  }
}

I used console.log("here"); in the setter function, which will be called for changing the opacity state via refs. There are 16 images, so initially it is called 16 times. But when I clicked on the shuffle button, you can see that it is called fewer than 16 times because some of the pictures show up directly without fading in.

I been struggling with this problem for days and really hope someone can give me some hints.

The problem is that your are adding only some new images in the shuffle method, one approach is to apply 0 opacity to all refs first, then wait a few ms to add 1 opacity again, like here .

But, I would recommend a better approach for animation, I love shifty and its Tweenable module.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM