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", "sass": "^1.58.0",
"unstated-next": "^1.1.0", "unstated-next": "^1.1.0",
"uuid": "^9.0.0", "uuid": "^9.0.0",
"waterfalljs-layout": "^0.1.0",
"web-vitals": "^2.1.4" "web-vitals": "^2.1.4"
}, },
"scripts": { "scripts": {

View File

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

View File

@ -1,20 +1,8 @@
#react-waterfall-comps li > div { .waterfall_outer {
transition: all 0.5s;
position: relative;
border-radius: 10px;
background-color: rgb(66, 66, 66);
padding: 10px;
display: flex; display: flex;
flex-direction: column; flex-direction: row;
transition: 0.3s; flex-wrap: wrap;
cursor: pointer; .waterfall_column {
} width: 40%;
#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%;
} }

View File

@ -3,15 +3,16 @@ import { AnimationOnScroll } from "react-animation-on-scroll";
import "../assets/stylesheets/project.scss"; import "../assets/stylesheets/project.scss";
import { useContainer } from "unstated-next"; import { useContainer } from "unstated-next";
import GlobalStore from "../store/global"; import GlobalStore from "../store/global";
import { Image } from 'antd'; import { Image } from "antd";
import projects from '../assets/data/projects'; import projects from "../assets/data/projects";
import WaterfallPositionDemo from "./Waterfall";
const Project = () => { const Project = () => {
useEffect(() => { useEffect(() => {
window.scrollTo(0, 0); window.scrollTo(0, 0);
}, []); }, []);
const {bodySize} = useContainer(GlobalStore); const { bodySize } = useContainer(GlobalStore);
const count = useMemo(() => { const count = useMemo(() => {
if (bodySize.width > 850) { if (bodySize.width > 850) {
return 3; return 3;
@ -25,6 +26,26 @@ const Project = () => {
<div className="project"> <div className="project">
<div className="project__content"> <div className="project__content">
<div className="project__content__main"> <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 <AnimationOnScroll
animateIn="animate__fadeInDown" animateIn="animate__fadeInDown"
animateOnce="true" animateOnce="true"
@ -38,7 +59,9 @@ const Project = () => {
className="project__content__main__container" className="project__content__main__container"
style={{ width: `calc(${100 / count}% - 16px)` }} 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"> <div className="project_item_content">
<Image width={"100%"} src={item.img}></Image> <Image width={"100%"} src={item.img}></Image>
<span>{item.content}</span> <span>{item.content}</span>
@ -53,7 +76,9 @@ const Project = () => {
className="project__content__main__container" className="project__content__main__container"
style={{ width: `calc(${100 / count}% - 16px)` }} 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"> <div className="project_item_content">
<Image width={"100%"} src={item.img}></Image> <Image width={"100%"} src={item.img}></Image>
<span>{item.content}</span> <span>{item.content}</span>
@ -61,34 +86,6 @@ const Project = () => {
</div> </div>
))} ))}
</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> </AnimationOnScroll>
</div> </div>
{/* <WaterfallPositionDemo /> */} {/* <WaterfallPositionDemo /> */}

View File

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