feat: add water fall pic
This commit is contained in:
		| @@ -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": { | ||||||
|   | |||||||
| @@ -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; | ||||||
|   | |||||||
| @@ -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%; |  | ||||||
| } | } | ||||||
| @@ -3,8 +3,9 @@ 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(() => { | ||||||
| @@ -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 /> */} | ||||||
|   | |||||||
| @@ -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(() => { | ||||||
|   const handleSearchImage = async () => { |     onSize(size); | ||||||
|     function random(min, max) { |   }, [size]); | ||||||
|       return min + Math.floor(Math.random() * (max - min + 1)); |   return <div ref={itemRef}>{itemRender}</div>; | ||||||
|     } |  | ||||||
|     const arr = []; |  | ||||||
|     for (let i = 0; i < 9; i++) { |  | ||||||
|       const imgSrc = `${defimages[i]}=${random(1, 10000)}`; |  | ||||||
|       arr.push(imgSrc); |  | ||||||
|     } |  | ||||||
|     setImages((prev) => [...prev, ...arr]); |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | 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; | ||||||
|  |     } | ||||||
|  |     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> | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user