feat: add water fall pic

This commit is contained in:
Jianqi Jin 2023-09-22 21:57:45 -05:00
parent a859b2824f
commit 43d66d50ae
5 changed files with 137 additions and 103 deletions

View File

@ -24,7 +24,6 @@
"sass": "^1.58.0",
"unstated-next": "^1.1.0",
"uuid": "^9.0.0",
"waterfalljs-layout": "^0.1.0",
"web-vitals": "^2.1.4"
},
"scripts": {

View File

@ -56,7 +56,7 @@
border-radius: 10px;
background-color: rgb(66, 66, 66);
box-sizing: border-box;
height: 400px;
// height: 400px;
display: flex;
flex-direction: column;
transition: 0.3s;

View File

@ -1,20 +1,8 @@
#react-waterfall-comps li > div {
transition: all 0.5s;
position: relative;
border-radius: 10px;
background-color: rgb(66, 66, 66);
padding: 10px;
.waterfall_outer {
display: flex;
flex-direction: column;
transition: 0.3s;
cursor: pointer;
}
#react-waterfall-comps li > div:hover {
transform: translateY(-6px);
box-shadow: 0 30px 50px rgba(0, 0, 0, 0.3);
transition: all 0.3s;
background-color: #666666;
}
#react-waterfall-comps li > div > img {
width: 100%;
}
flex-direction: row;
flex-wrap: wrap;
.waterfall_column {
width: 40%;
}
}

View File

@ -3,15 +3,16 @@ import { AnimationOnScroll } from "react-animation-on-scroll";
import "../assets/stylesheets/project.scss";
import { useContainer } from "unstated-next";
import GlobalStore from "../store/global";
import { Image } from 'antd';
import projects from '../assets/data/projects';
import { Image } from "antd";
import projects from "../assets/data/projects";
import WaterfallPositionDemo from "./Waterfall";
const Project = () => {
useEffect(() => {
window.scrollTo(0, 0);
}, []);
const {bodySize} = useContainer(GlobalStore);
const { bodySize } = useContainer(GlobalStore);
const count = useMemo(() => {
if (bodySize.width > 850) {
return 3;
@ -25,6 +26,26 @@ const Project = () => {
<div className="project">
<div className="project__content">
<div className="project__content__main">
{/* <WaterfallPositionDemo
columnNumber={count}
list={projects.active.map((item) => {
return {
itemRender: (
<div
className="project__content__main__container"
>
<h3 style={{ color: "#fff", marginBottom: 12 }}>
{item.title}
</h3>
<div className="project_item_content">
<Image width={"100%"} src={item.img}></Image>
<span>{item.content}</span>
</div>
</div>
),
};
})}
/> */}
<AnimationOnScroll
animateIn="animate__fadeInDown"
animateOnce="true"
@ -38,7 +59,9 @@ const Project = () => {
className="project__content__main__container"
style={{ width: `calc(${100 / count}% - 16px)` }}
>
<h3 style={{ color: "#fff", marginBottom: 12 }}>{item.title}</h3>
<h3 style={{ color: "#fff", marginBottom: 12 }}>
{item.title}
</h3>
<div className="project_item_content">
<Image width={"100%"} src={item.img}></Image>
<span>{item.content}</span>
@ -53,7 +76,9 @@ const Project = () => {
className="project__content__main__container"
style={{ width: `calc(${100 / count}% - 16px)` }}
>
<h3 style={{ color: "#fff", marginBottom: 12 }}>{item.title}</h3>
<h3 style={{ color: "#fff", marginBottom: 12 }}>
{item.title}
</h3>
<div className="project_item_content">
<Image width={"100%"} src={item.img}></Image>
<span>{item.content}</span>
@ -61,34 +86,6 @@ const Project = () => {
</div>
))}
</div>
{/* <div
style={{
height: "100vh",
width: "100vw",
border: "1px solid",
marginTop: "30px",
overflowY: "scroll",
}}
>
<Waterfall
columnWidth={236}
columnCount={2}
columnGap={24}
rowGap={24}
onChangeUlMaxH={(h) => (ulMaxHRef.current = h)}
>
{images.map((item, index) => {
return (
<li key={index} onClick={() => alert("图片地址为:" + item)}>
<div>
{index + 1}
<img src={item} alt="" />
</div>
</li>
);
})}
</Waterfall>
</div> */}
</AnimationOnScroll>
</div>
{/* <WaterfallPositionDemo /> */}

View File

@ -1,5 +1,12 @@
import React, { useState, useRef } from "react";
import Waterfall from "waterfalljs-layout/react";
import {
useDebounce,
useDebounceFn,
useSetState,
useSize,
useThrottle,
useThrottleFn,
} from "ahooks";
import React, { useRef, useEffect } from "react";
import "../assets/stylesheets/waterfall.scss";
const defimages = [
@ -15,57 +22,100 @@ const defimages = [
"https://picsum.photos/720/640/?random",
];
export default function WaterfallPositionDemo() {
const [images, setImages] = useState(defimages);
const ulMaxHRef = useRef(0);
const Item = ({ itemRender, onSize }) => {
const itemRef = useRef();
const size = useSize(itemRef.current);
useEffect(() => {
onSize(size);
}, [size]);
return <div ref={itemRef}>{itemRender}</div>;
};
const handleSearchImage = async () => {
function random(min, max) {
return min + Math.floor(Math.random() * (max - min + 1));
export default function WaterfallPositionDemo({ columnNumber, list }) {
const [columns, setColumns] = useSetState(
new Array(columnNumber).fill(0).map((item) => [])
);
const listRef = useRef(list);
// useEffect(() => {
// listRef.current = list;
// }, [list]);
useEffect(() => {
// fill the columns
const initColumns = new Array(columnNumber).fill(0).map((item) => []);
list.forEach((item, index) => {
item.size = {
width: 0,
height: 0,
};
item.index = index;
const i = index % columnNumber;
initColumns[i].push(item);
});
listRef.current = list;
setColumns(initColumns);
}, []);
const onSizeRef = useRef(null);
const onSize = ({ item: itm, columnIndex: key, index, size }) => {
if (onSizeRef.current) {
return;
}
const arr = [];
for (let i = 0; i < 9; i++) {
const imgSrc = `${defimages[i]}=${random(1, 10000)}`;
arr.push(imgSrc);
onSizeRef.current = true;
if (itm && size && listRef.current[itm.index]) {
listRef.current[itm.index].size = size;
}
setImages((prev) => [...prev, ...arr]);
const initColumns = new Array(columnNumber).fill(0).map((item) => []);
const heights = new Array(columnNumber).fill(0).map((item) => 0);
console.log("listRef.current", listRef.current.length);
listRef.current.forEach((item, index) => {
let i = 0;
let minHeight = Infinity;
for (let tmpI = 0; tmpI < heights.length; ++tmpI) {
if (heights[tmpI] < minHeight) {
minHeight = heights[tmpI];
i = tmpI;
}
}
console.log("minHeight", minHeight, i);
heights[i] += item?.size?.height || 0;
initColumns[i].push(item);
});
setColumns(initColumns);
console.log("minHeight", initColumns);
onSizeRef.current = false;
};
const columnsDebounce = useDebounce(columns, {
wait: 50,
});
return (
<div
style={{
height: "600px",
width: "520px",
border: "1px solid",
marginTop: "30px",
overflowY: "scroll",
}}
>
<Waterfall
columnWidth={236}
columnCount={2}
columnGap={24}
rowGap={24}
onChangeUlMaxH={(h) => (ulMaxHRef.current = h)}
>
{images.map((item, index) => {
return (
<li key={index} onClick={() => alert("图片地址为:" + item)}>
<div>
{index + 1}
<img src={item} alt="" />
</div>
</li>
);
})}
</Waterfall>
<div style={{ textAlign: "center" }}>
<button
onClick={() => handleSearchImage()}
style={{ margin: "30px auto" }}
>
LOAD MORE
</button>
</div>
<div className="waterfall_outer">
{Object.keys(columnsDebounce).map((key) => {
const item = columnsDebounce[key];
return (
<div
key={`${new Date()}_${key}`}
className="waterfall_column"
style={{ width: `calc(${100 / columnNumber}% - 16px)` }}
>
{item.map((itm, index) => {
return (
<Item
key={`${new Date()}_${itm.index}_${index}`}
itemRender={itm.itemRender}
onSize={(size) =>
onSize({
item: itm,
columnIndex: key,
index,
size,
})
}
/>
);
})}
</div>
);
})}
</div>
);
}