From 43d66d50ae291b432307f8fd8106c7ff96f1b067 Mon Sep 17 00:00:00 2001 From: Jianqi Jin Date: Fri, 22 Sep 2023 21:57:45 -0500 Subject: [PATCH 1/2] feat: add water fall pic --- package.json | 1 - src/assets/stylesheets/project.scss | 2 +- src/assets/stylesheets/waterfall.scss | 26 ++--- src/components/Projects.js | 65 ++++++------ src/components/Waterfall.js | 146 +++++++++++++++++--------- 5 files changed, 137 insertions(+), 103 deletions(-) diff --git a/package.json b/package.json index 1a4154a..6f4e82e 100644 --- a/package.json +++ b/package.json @@ -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": { diff --git a/src/assets/stylesheets/project.scss b/src/assets/stylesheets/project.scss index a1d111e..b33d0fa 100644 --- a/src/assets/stylesheets/project.scss +++ b/src/assets/stylesheets/project.scss @@ -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; diff --git a/src/assets/stylesheets/waterfall.scss b/src/assets/stylesheets/waterfall.scss index 4d89ea9..e214aad 100644 --- a/src/assets/stylesheets/waterfall.scss +++ b/src/assets/stylesheets/waterfall.scss @@ -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%; + } +} \ No newline at end of file diff --git a/src/components/Projects.js b/src/components/Projects.js index f6f9f99..9682c89 100644 --- a/src/components/Projects.js +++ b/src/components/Projects.js @@ -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 = () => {
+ {/* { + return { + itemRender: ( +
+

+ {item.title} +

+
+ + {item.content} +
+
+ ), + }; + })} + /> */} { className="project__content__main__container" style={{ width: `calc(${100 / count}% - 16px)` }} > -

{item.title}

+

+ {item.title} +

{item.content} @@ -53,7 +76,9 @@ const Project = () => { className="project__content__main__container" style={{ width: `calc(${100 / count}% - 16px)` }} > -

{item.title}

+

+ {item.title} +

{item.content} @@ -61,34 +86,6 @@ const Project = () => {
))}
- {/*
- (ulMaxHRef.current = h)} - > - {images.map((item, index) => { - return ( -
  • alert("图片地址为:" + item)}> -
    - {index + 1} - -
    -
  • - ); - })} -
    -
    */}
    {/* */} diff --git a/src/components/Waterfall.js b/src/components/Waterfall.js index 1de51e5..9a38fa0 100644 --- a/src/components/Waterfall.js +++ b/src/components/Waterfall.js @@ -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
    {itemRender}
    ; +}; - 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 ( -
    - (ulMaxHRef.current = h)} - > - {images.map((item, index) => { - return ( -
  • alert("图片地址为:" + item)}> -
    - {index + 1} - -
    -
  • - ); - })} -
    -
    - -
    +
    + {Object.keys(columnsDebounce).map((key) => { + const item = columnsDebounce[key]; + return ( +
    + {item.map((itm, index) => { + return ( + + onSize({ + item: itm, + columnIndex: key, + index, + size, + }) + } + /> + ); + })} +
    + ); + })}
    ); } From a883ebe2ef042505d95667a345a297bb21ef12e2 Mon Sep 17 00:00:00 2001 From: Jianqi Jin Date: Tue, 26 Sep 2023 19:25:53 -0500 Subject: [PATCH 2/2] modify test --- src/assets/stylesheets/project.scss | 4 +- src/assets/stylesheets/waterfall.scss | 7 +- src/components/Projects.js | 70 ++--------- src/components/Waterfall.js | 171 +++++++++++--------------- 4 files changed, 85 insertions(+), 167 deletions(-) diff --git a/src/assets/stylesheets/project.scss b/src/assets/stylesheets/project.scss index b33d0fa..920ceeb 100644 --- a/src/assets/stylesheets/project.scss +++ b/src/assets/stylesheets/project.scss @@ -32,7 +32,7 @@ justify-content: start; } .projects__title { - margin: 20px 0 0 20px; + margin: 20px 0 20px 20px; font-family: itrFontMedium; color: #fff; } @@ -47,8 +47,10 @@ width: 100vw; height: auto; display: flex; + flex-direction: column; justify-content: center; align-items: center; + padding-top: 24px; } .project__content__main__container { diff --git a/src/assets/stylesheets/waterfall.scss b/src/assets/stylesheets/waterfall.scss index e214aad..ec50dd3 100644 --- a/src/assets/stylesheets/waterfall.scss +++ b/src/assets/stylesheets/waterfall.scss @@ -1,8 +1,7 @@ -.waterfall_outer { +.waterfallContainer { display: flex; - flex-direction: row; flex-wrap: wrap; - .waterfall_column { - width: 40%; + .waterfallItem { + margin: 3px; } } \ No newline at end of file diff --git a/src/components/Projects.js b/src/components/Projects.js index 9682c89..848522e 100644 --- a/src/components/Projects.js +++ b/src/components/Projects.js @@ -1,11 +1,10 @@ -import React, { useEffect, useMemo } from "react"; -import { AnimationOnScroll } from "react-animation-on-scroll"; +import React, { forwardRef, useEffect, useMemo } from "react"; 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 WaterfallPositionDemo from "./Waterfall"; +import WaterfallPosition from "./Waterfall"; const Project = () => { useEffect(() => { @@ -26,67 +25,14 @@ const Project = () => {
    - {/* { - return { - itemRender: ( -
    -

    - {item.title} -

    -
    - - {item.content} -
    -
    - ), - }; - })} - /> */} - +

    Active Projects

    -
    - {projects.active.map((item) => ( -
    -

    - {item.title} -

    -
    - - {item.content} -
    -
    - ))} -
    + +
    +

    Retired/Inactive Projects

    -
    - {projects.inactive.map((item) => ( -
    -

    - {item.title} -

    -
    - - {item.content} -
    -
    - ))} -
    - + +
    {/* */}
    diff --git a/src/components/Waterfall.js b/src/components/Waterfall.js index 9a38fa0..28d3a95 100644 --- a/src/components/Waterfall.js +++ b/src/components/Waterfall.js @@ -1,121 +1,92 @@ -import { - useDebounce, - useDebounceFn, - useSetState, - useSize, - useThrottle, - useThrottleFn, -} from "ahooks"; -import React, { useRef, useEffect } from "react"; +import { useSize } from "ahooks"; +import React, { useRef, useEffect, useState } from "react"; import "../assets/stylesheets/waterfall.scss"; +import { Image } from "antd"; -const defimages = [ - "https://picsum.photos/640/200/?random", - "https://picsum.photos/360/640/?random", - "https://picsum.photos/480/720/?random", - "https://picsum.photos/480/640/?random", - "https://picsum.photos/360/?random", - "https://picsum.photos/360/520/?random", - "https://picsum.photos/520/360/?random", - "https://picsum.photos/520/360/?random", - "https://picsum.photos/520/360/?random", - "https://picsum.photos/720/640/?random", -]; - -const Item = ({ itemRender, onSize }) => { - const itemRef = useRef(); - const size = useSize(itemRef.current); +const WaterfallItem = ({ data, onLoad }) => { + const ref = useRef(); + const size = useSize(ref); + const sizeRef = useRef({}); useEffect(() => { - onSize(size); + sizeRef.current.size = size; }, [size]); - return
    {itemRender}
    ; + return ( +
    +
    +

    {data.title}

    +
    + { + setTimeout(() => { + onLoad(sizeRef.current.size); + }, 500); + }} + alt="asd" + onError={setTimeout(() => { + onLoad(sizeRef.current.size); + }, 500)} + width={"100%"} + src={data.img} + /> + {data.content} +
    +
    +
    + ); }; -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 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(); } - 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; + }; + const [columns, setColumns] = useState([[], [], [], []]); + const onSize = () => { + let res = [[], [], [], []]; + let columnHeights = [0, 0, 0, 0]; + rendered.map((renderItem, index) => { let minHeight = Infinity; - for (let tmpI = 0; tmpI < heights.length; ++tmpI) { - if (heights[tmpI] < minHeight) { - minHeight = heights[tmpI]; - i = tmpI; + let minHeightIndex = 0; + for (let i = 0; i < columnNumber; ++i) { + if (minHeight > columnHeights[i]) { + minHeight = columnHeights[i]; + minHeightIndex = i; } } - console.log("minHeight", minHeight, i); - heights[i] += item?.size?.height || 0; - initColumns[i].push(item); + res[minHeightIndex].push(renderItem); + columnHeights[minHeightIndex] += stateRef.current.heights[minHeightIndex]; }); - setColumns(initColumns); - - console.log("minHeight", initColumns); - onSizeRef.current = false; + setColumns(res); }; - const columnsDebounce = useDebounce(columns, { - wait: 50, - }); + const waterfallDOM = useRef(); + const size = useSize(waterfallDOM); + useEffect(() => { + onSize(); + }, [size, columnNumber]); + const rendered = list.map((item, index) => ( + onload(index, size.height)} data={item} /> + )); return ( -
    - {Object.keys(columnsDebounce).map((key) => { - const item = columnsDebounce[key]; +
    + {columns.map((column) => { return (
    - {item.map((itm, index) => { - return ( - - onSize({ - item: itm, - columnIndex: key, - index, - size, - }) - } - /> - ); - })} + {column}
    ); })}
    ); -} +}; +export default WaterfallPosition;