add waterfall pic wall
This commit is contained in:
		| @@ -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": { | ||||
|   | ||||
| @@ -33,7 +33,7 @@ | ||||
|   justify-content: start; | ||||
| } | ||||
| .projects__title { | ||||
|   margin: 20px 0 0 20px; | ||||
|   margin: 20px 0 20px 20px; | ||||
|   font-family: itrFontMedium; | ||||
|   color: #fff; | ||||
|   text-align: center; | ||||
| @@ -49,8 +49,10 @@ | ||||
|   width: 100vw; | ||||
|   height: auto; | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   justify-content: center; | ||||
|   align-items: center; | ||||
|   padding-top: 24px; | ||||
| } | ||||
|  | ||||
| .project__content__main__container { | ||||
| @@ -58,7 +60,6 @@ | ||||
|   border-radius: 10px; | ||||
|   background-color: rgb(66, 66, 66); | ||||
|   box-sizing: border-box; | ||||
|   height: auto; | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   transition: 0.3s; | ||||
|   | ||||
| @@ -1,20 +1,7 @@ | ||||
| #react-waterfall-comps li > div { | ||||
|   transition: all 0.5s; | ||||
|   position: relative; | ||||
|   border-radius: 10px; | ||||
|   background-color: rgb(66, 66, 66); | ||||
|   padding: 10px; | ||||
| .waterfallContainer { | ||||
|   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-wrap: wrap; | ||||
|   .waterfallItem { | ||||
|     margin: 3px; | ||||
|   } | ||||
| } | ||||
| @@ -1,17 +1,16 @@ | ||||
| import React, { useEffect, useMemo } from "react"; | ||||
| 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 projects from "../assets/data/projects"; | ||||
| import WaterfallPosition 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,77 +24,14 @@ const Project = () => { | ||||
|     <div className="project"> | ||||
|       <div className="project__content"> | ||||
|         <div className="project__content__main"> | ||||
|           <AnimationOnScroll | ||||
|             animateIn="animate__fadeInDown" | ||||
|             animateOnce="true" | ||||
|             duration={1} | ||||
|             delay={0} | ||||
|           > | ||||
|           <div> | ||||
|             <h1 className="projects__title">Active Projects</h1> | ||||
|             <div className="projects_wrap" size={16}> | ||||
|               {projects.active.map((item) => ( | ||||
|                 <div | ||||
|                   className="project__content__main__container" | ||||
|                   style={{ width: `calc(${100 / count}% - 16px)` }} | ||||
|                 > | ||||
|                   <div style={{ display: 'flex', flexDirection: 'row', justifyContent:'space-between'  }}> | ||||
|                     <h3 style={{ fontFamily: "itrFontMedium", fontSize: '25px', color: "#fff", marginBottom: 12 }}>{item.title}</h3> | ||||
|                     <h3 style={{ fontFamily: "itrFontMedium", fontSize: '25px', color: "#fff", marginBottom: 12 }}>{item.sub}</h3> | ||||
|                   </div> | ||||
|                   <div className="project_item_content"> | ||||
|                     <Image className="project_item_content_image" width={"100%"} src={item.img}></Image> | ||||
|                     <span>{item.content}</span> | ||||
|                   </div> | ||||
|                 </div> | ||||
|               ))} | ||||
|             </div> | ||||
|             <h1 className="projects__title">Retired Projects</h1> | ||||
|             <div className="projects_wrap" size={16}> | ||||
|               {projects.inactive.map((item) => ( | ||||
|                 <div | ||||
|                   className="project__content__main__container" | ||||
|                   style={{ width: `calc(${100 / count}% - 16px)`}} | ||||
|                 > | ||||
|                   <div style={{ display: 'flex', flexDirection: 'row', justifyContent:'space-between'  }}> | ||||
|                     <h3 style={{ fontFamily: "itrFontMedium", fontSize: '25px', color: "#fff", marginBottom: 12 }}>{item.title}</h3> | ||||
|                     <h3 style={{ fontFamily: "itrFontMedium", fontSize: '25px', color: "#fff", marginBottom: 12 }}>{item.sub}</h3> | ||||
|                   </div> | ||||
|                   <div className="project_item_content"> | ||||
|                     <Image className="project_item_content_image" width={"100%"} src={item.img}></Image> | ||||
|                     <span>{item.content}</span> | ||||
|                   </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> | ||||
|             <WaterfallPosition columnNumber={count} list={projects.active} /> | ||||
|           </div> | ||||
|           <div> | ||||
|             <h1 className="projects__title">Retired/Inactive Projects</h1> | ||||
|             <WaterfallPosition columnNumber={count} list={projects.inactive} /> | ||||
|           </div> | ||||
|         </div> | ||||
|         {/* <WaterfallPositionDemo /> */} | ||||
|       </div> | ||||
|   | ||||
| @@ -1,71 +1,95 @@ | ||||
| import React, { useState, useRef } from "react"; | ||||
| import Waterfall from "waterfalljs-layout/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", | ||||
| ]; | ||||
|  | ||||
| export default function WaterfallPositionDemo() { | ||||
|   const [images, setImages] = useState(defimages); | ||||
|   const ulMaxHRef = useRef(0); | ||||
|  | ||||
|   const handleSearchImage = async () => { | ||||
|     function random(min, max) { | ||||
|       return min + Math.floor(Math.random() * (max - min + 1)); | ||||
|     } | ||||
|     const arr = []; | ||||
|     for (let i = 0; i < 9; i++) { | ||||
|       const imgSrc = `${defimages[i]}=${random(1, 10000)}`; | ||||
|       arr.push(imgSrc); | ||||
|     } | ||||
|     setImages((prev) => [...prev, ...arr]); | ||||
|   }; | ||||
| const WaterfallItem = ({ data, onLoad }) => { | ||||
|   const ref = useRef(); | ||||
|   const size = useSize(ref); | ||||
|   const sizeRef = useRef({}); | ||||
|   useEffect(() => { | ||||
|     sizeRef.current.size = size; | ||||
|   }, [size]); | ||||
|   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 className="waterfallItem" ref={ref}> | ||||
|       <div className="project__content__main__container"> | ||||
|         <div style={{ display: 'flex', flexDirection: 'row', justifyContent:'space-between'  }}> | ||||
|           <h3 style={{ fontFamily: "itrFontMedium", fontSize: '25px', color: "#fff", marginBottom: 12 }}>{data.title}</h3> | ||||
|           <h3 style={{ fontFamily: "itrFontMedium", fontSize: '25px', color: "#fff", marginBottom: 12 }}>{data.sub}</h3> | ||||
|         </div> | ||||
|         <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; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user