93 lines
2.5 KiB
JavaScript
93 lines
2.5 KiB
JavaScript
import { useSize } from "ahooks";
|
|
import React, { useRef, useEffect, useState } from "react";
|
|
import "../assets/stylesheets/waterfall.scss";
|
|
import { Image } from "antd";
|
|
|
|
const WaterfallItem = ({ data, onLoad }) => {
|
|
const ref = useRef();
|
|
const size = useSize(ref);
|
|
const sizeRef = useRef({});
|
|
useEffect(() => {
|
|
sizeRef.current.size = size;
|
|
}, [size]);
|
|
return (
|
|
<div className="waterfallItem" ref={ref}>
|
|
<div className="project__content__main__container">
|
|
<h3 style={{ color: "#fff", marginBottom: 12 }}>{data.title}</h3>
|
|
<div className="project_item_content">
|
|
<Image
|
|
onLoad={() => {
|
|
setTimeout(() => {
|
|
onLoad(sizeRef.current.size);
|
|
}, 500);
|
|
}}
|
|
alt="asd"
|
|
onError={setTimeout(() => {
|
|
onLoad(sizeRef.current.size);
|
|
}, 500)}
|
|
width={"100%"}
|
|
src={data.img}
|
|
/>
|
|
<span>{data.content}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const WaterfallPosition = ({ columnNumber, list }) => {
|
|
const stateRef = useRef({
|
|
heights: [],
|
|
loadNum: 0,
|
|
});
|
|
const onload = (index, height) => {
|
|
stateRef.current.heights[index] = height;
|
|
stateRef.current.loadNum++;
|
|
if (stateRef.current.loadNum === list.length) {
|
|
onSize();
|
|
}
|
|
};
|
|
const [columns, setColumns] = useState([[], [], [], []]);
|
|
const onSize = () => {
|
|
let res = [[], [], [], []];
|
|
let columnHeights = [0, 0, 0, 0];
|
|
rendered.map((renderItem, index) => {
|
|
let minHeight = Infinity;
|
|
let minHeightIndex = 0;
|
|
for (let i = 0; i < columnNumber; ++i) {
|
|
if (minHeight > columnHeights[i]) {
|
|
minHeight = columnHeights[i];
|
|
minHeightIndex = i;
|
|
}
|
|
}
|
|
res[minHeightIndex].push(renderItem);
|
|
columnHeights[minHeightIndex] += stateRef.current.heights[minHeightIndex];
|
|
});
|
|
setColumns(res);
|
|
};
|
|
const waterfallDOM = useRef();
|
|
const size = useSize(waterfallDOM);
|
|
useEffect(() => {
|
|
onSize();
|
|
}, [size, columnNumber]);
|
|
const rendered = list.map((item, index) => (
|
|
<WaterfallItem onLoad={(size) => onload(index, size.height)} data={item} />
|
|
));
|
|
return (
|
|
<div ref={waterfallDOM} className="waterfallContainer">
|
|
{columns.map((column) => {
|
|
return (
|
|
<div
|
|
style={{
|
|
width: `calc(${100 / columnNumber}% - 16px)`,
|
|
}}
|
|
>
|
|
{column}
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
};
|
|
export default WaterfallPosition;
|