diff --git a/docs/package.json b/docs/package.json index db0654fcf..d3fb494de 100644 --- a/docs/package.json +++ b/docs/package.json @@ -22,6 +22,7 @@ "antd": "^5.27.5", "clsx": "^2.0.0", "echarts": "^5.6.0", + "gsap": "^3.14.2", "octokit": "^5.0.5", "prism-react-renderer": "^2.3.0", "react": "^19.0.0", diff --git a/docs/src/components/HomePage/index.js b/docs/src/components/HomePage/index.js index 4ddacb8dd..c7cdd730f 100644 --- a/docs/src/components/HomePage/index.js +++ b/docs/src/components/HomePage/index.js @@ -5,6 +5,7 @@ import clsx from 'clsx'; import dayjs from 'dayjs'; import CountUp from 'react-countup'; import Translate from '@docusaurus/Translate'; +import { gsap } from 'gsap'; import Header from './Header'; import styles from './styles.module.css'; @@ -130,6 +131,44 @@ export default ({ currentLocale }) => { }) }, []); + // 鼠标跟随边框高亮效果 + useEffect(() => { + const featuresSection = featuresRef.current; + if (!featuresSection) return; + + const cards = featuresSection.querySelectorAll(`.${styles.card}`); + + const handleMouseMove = (e) => { + const rect = featuresSection.getBoundingClientRect(); + const mouseX = e.clientX - rect.left; + const mouseY = e.clientY - rect.top; + + cards.forEach((card) => { + const cardRect = card.getBoundingClientRect(); + const cardX = cardRect.left - rect.left; + const cardY = cardRect.top - rect.top; + + // 计算鼠标相对于卡片的位置 + const relativeX = mouseX - cardX; + const relativeY = mouseY - cardY; + + // 使用 gsap 动画更新 CSS 变量 + gsap.to(card, { + '--mouse-x': `${relativeX}px`, + '--mouse-y': `${relativeY}px`, + duration: 0.2, + ease: 'power2.out' + }); + }); + }; + + featuresSection.addEventListener('mousemove', handleMouseMove); + + return () => { + featuresSection.removeEventListener('mousemove', handleMouseMove); + }; + }, []); + return
diff --git a/docs/src/components/HomePage/styles.module.css b/docs/src/components/HomePage/styles.module.css index a265c23d5..ae98b9806 100644 --- a/docs/src/components/HomePage/styles.module.css +++ b/docs/src/components/HomePage/styles.module.css @@ -179,6 +179,48 @@ box-sizing: border-box; border: 1px solid rgba(255, 255, 255, 0.2); padding: 32px; + position: relative; + --mouse-x: 50%; + --mouse-y: 50%; + overflow: hidden; + + &::before { + content: ''; + position: absolute; + inset: 0; + border-radius: 32px; + padding: 2px; + background: transparent; + -webkit-mask: + linear-gradient(#fff 0 0) content-box, + linear-gradient(#fff 0 0); + -webkit-mask-composite: xor; + mask-composite: exclude; + pointer-events: none; + z-index: 1; + } + + &::after { + content: ''; + position: absolute; + inset: 0; + border-radius: 32px; + padding: 2px; + background: radial-gradient( + 400px circle at var(--mouse-x) var(--mouse-y), + rgba(120, 80, 255, 1), + rgba(120, 80, 255, 0.6) 30%, + transparent 50% + ); + -webkit-mask: + linear-gradient(#fff 0 0) content-box, + linear-gradient(#fff 0 0); + -webkit-mask-composite: xor; + mask-composite: exclude; + opacity: 1; + pointer-events: none; + z-index: 2; + } .subTitle { margin-top: 16px; font-family: Inter;