From 47f880d280a1e552eb1f3ec3706018be92e9f9ed Mon Sep 17 00:00:00 2001 From: wkylin Date: Mon, 2 Dec 2024 19:43:21 +0800 Subject: [PATCH] feat: type loop --- package-lock.json | 34 ++++++++++ package.json | 2 + src/components/stateless/Spotlight/index.jsx | 67 ++++++++++++++++++++ src/pages/home/index.jsx | 33 +++++++++- 4 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 src/components/stateless/Spotlight/index.jsx diff --git a/package-lock.json b/package-lock.json index d02f06f3..3c1a8286 100644 --- a/package-lock.json +++ b/package-lock.json @@ -65,6 +65,7 @@ "react": "^18.3.1", "react-barcode": "^1.5.3", "react-canvas-confetti": "^2.0.7", + "react-countup": "^6.5.3", "react-css-theme-switcher": "^0.3.0", "react-dom": "^18.3.1", "react-error-boundary": "^4.1.2", @@ -102,6 +103,7 @@ "styled-components": "^6.1.13", "three": "^0.170.0", "typescript": "^5.7.2", + "typewriter-effect": "^2.21.0", "use-debounce": "^10.0.4", "use-deep-compare-effect": "^1.8.1", "use-react-router-breadcrumbs": "^4.0.1", @@ -14775,6 +14777,12 @@ "typescript": ">=4" } }, + "node_modules/countup.js": { + "version": "2.8.0", + "resolved": "https://registry.npmmirror.com/countup.js/-/countup.js-2.8.0.tgz", + "integrity": "sha512-f7xEhX0awl4NOElHulrl4XRfKoNH3rB+qfNSZZyjSZhaAoUk6elvhH+MNxMmlmuUJ2/QNTWPSA7U4mNtIAKljQ==", + "license": "MIT" + }, "node_modules/create-ecdh": { "version": "4.0.4", "license": "MIT", @@ -31281,6 +31289,18 @@ "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-countup": { + "version": "6.5.3", + "resolved": "https://registry.npmmirror.com/react-countup/-/react-countup-6.5.3.tgz", + "integrity": "sha512-udnqVQitxC7QWADSPDOxVWULkLvKUWrDapn5i53HE4DPRVgs+Y5rr4bo25qEl8jSh+0l2cToJgGMx+clxPM3+w==", + "license": "MIT", + "dependencies": { + "countup.js": "^2.8.0" + }, + "peerDependencies": { + "react": ">= 16.3.0" + } + }, "node_modules/react-css-theme-switcher": { "version": "0.3.0", "license": "MIT", @@ -37334,6 +37354,20 @@ "node": ">=14.17" } }, + "node_modules/typewriter-effect": { + "version": "2.21.0", + "resolved": "https://registry.npmmirror.com/typewriter-effect/-/typewriter-effect-2.21.0.tgz", + "integrity": "sha512-Y3VL1fuJpUBj0gS4OTXBLzy1gnYTYaBuVuuO99tGNyTkkub5CXi+b/hsV7Og9fp6HlhogOwWJwgq7iXI5sQlEg==", + "license": "MIT", + "dependencies": { + "prop-types": "^15.8.1", + "raf": "^3.4.1" + }, + "peerDependencies": { + "react": "^17.x || ^18.x", + "react-dom": "^17.x || ^18.x" + } + }, "node_modules/uc.micro": { "version": "2.1.0", "license": "MIT" diff --git a/package.json b/package.json index bcc4a5df..b7022896 100644 --- a/package.json +++ b/package.json @@ -268,6 +268,7 @@ "react": "^18.3.1", "react-barcode": "^1.5.3", "react-canvas-confetti": "^2.0.7", + "react-countup": "^6.5.3", "react-css-theme-switcher": "^0.3.0", "react-dom": "^18.3.1", "react-error-boundary": "^4.1.2", @@ -305,6 +306,7 @@ "styled-components": "^6.1.13", "three": "^0.170.0", "typescript": "^5.7.2", + "typewriter-effect": "^2.21.0", "use-debounce": "^10.0.4", "use-deep-compare-effect": "^1.8.1", "use-react-router-breadcrumbs": "^4.0.1", diff --git a/src/components/stateless/Spotlight/index.jsx b/src/components/stateless/Spotlight/index.jsx new file mode 100644 index 00000000..b6eec03d --- /dev/null +++ b/src/components/stateless/Spotlight/index.jsx @@ -0,0 +1,67 @@ +import React, { useRef, useState, useEffect } from "react" +import useMousePosition from "@hooks/useMousePosition" + +export default function Spotlight({children, className = "",}) { + const containerRef = useRef(null); + const mousePosition = useMousePosition(); + const mouse = useRef({ x: 0, y: 0 }); + const containerSize = useRef({ w: 0, h: 0 }); + const [boxes, setBoxes] = useState([]); + + useEffect(() => { + containerRef.current && + setBoxes( + Array.from(containerRef.current.children).map( + (el) => el, + ), + ); + }, []); + + useEffect(() => { + initContainer(); + window.addEventListener("resize", initContainer); + + return () => { + window.removeEventListener("resize", initContainer); + }; + }, [boxes]); + + useEffect(() => { + onMouseMove(); + }, [mousePosition]); + + const initContainer = () => { + if (containerRef.current) { + containerSize.current.w = containerRef.current.offsetWidth; + containerSize.current.h = containerRef.current.offsetHeight; + } + }; + + const onMouseMove = () => { + if (containerRef.current) { + const rect = containerRef.current.getBoundingClientRect(); + const { w, h } = containerSize.current; + const x = mousePosition.x - rect.left; + const y = mousePosition.y - rect.top; + const inside = x < w && x > 0 && y < h && y > 0; + if (inside) { + mouse.current.x = x; + mouse.current.y = y; + boxes.forEach((box) => { + const boxX = + -(box.getBoundingClientRect().left - rect.left) + mouse.current.x; + const boxY = + -(box.getBoundingClientRect().top - rect.top) + mouse.current.y; + box.style.setProperty("--mouse-x", `${boxX}px`); + box.style.setProperty("--mouse-y", `${boxY}px`); + }); + } + } + }; + + return ( +
+ {children} +
+ ); +} diff --git a/src/pages/home/index.jsx b/src/pages/home/index.jsx index 2588f5f1..41c5e09d 100644 --- a/src/pages/home/index.jsx +++ b/src/pages/home/index.jsx @@ -2,7 +2,10 @@ import React, { version, useState, useRef } from 'react' import { Input, Flex, Button } from 'antd' import { SendOutlined } from '@ant-design/icons' import { Atom, Merge, GitMerge, GitPullRequestArrow } from 'lucide-react' +import CountUp from 'react-countup' import { PinInput } from 'react-input-pin-code' +import Spotlight from '@stateless/Spotlight' +import Typewriter from 'typewriter-effect' import FixTabPanel from '@stateless/FixTabPanel' import TypedText from '@stateless/TypedText' import ReMarkdown from '@stateless/ReMarkdown' @@ -187,6 +190,20 @@ const Home = () => { +
+ +
@@ -225,6 +242,12 @@ const Home = () => { + {/*
+ +
+
+
+
*/}
@@ -264,7 +287,15 @@ const Home = () => { - +
+ +