feat: 添加预览效果页面并优化交互效果
refactor: 优化代码健壮性和类型安全 style: 更新字体样式和全局CSS fix: 修复IntersectionObserver潜在空引用问题 chore: 更新依赖和ESLint配置 build: 更新构建ID和路由配置
This commit is contained in:
@@ -19,7 +19,7 @@ export function InkDrop({
|
||||
color = '#1C1C1C',
|
||||
blur = 0,
|
||||
delay = 0,
|
||||
duration = 8,
|
||||
duration: _duration = 8,
|
||||
className = ''
|
||||
}: InkDropProps) {
|
||||
return (
|
||||
@@ -251,7 +251,7 @@ export function FloatingInk({ count = 15, className = '' }: FloatingInkProps) {
|
||||
}, []);
|
||||
|
||||
const elements = useMemo(() => {
|
||||
if (!isMounted) return [];
|
||||
if (!isMounted) {return [];}
|
||||
const items = [];
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
@@ -351,12 +351,50 @@ interface InkDecorationProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function InkDecoration({ variant = 'balanced', className = '' }: InkDecorationProps) {
|
||||
const [isMounted, setIsMounted] = useState(false);
|
||||
interface DropPosition {
|
||||
left: string;
|
||||
top: string;
|
||||
size: number;
|
||||
opacity: number;
|
||||
blur: number;
|
||||
isRed: boolean;
|
||||
duration: number;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setIsMounted(true);
|
||||
}, []);
|
||||
interface SplashPosition {
|
||||
left: string;
|
||||
top: string;
|
||||
size: number;
|
||||
duration: number;
|
||||
}
|
||||
|
||||
interface SealPosition {
|
||||
left: string;
|
||||
top: string;
|
||||
size: number;
|
||||
duration: number;
|
||||
}
|
||||
|
||||
interface StainPosition {
|
||||
left: string;
|
||||
top: string;
|
||||
size: number;
|
||||
duration: number;
|
||||
}
|
||||
|
||||
interface StrokePosition {
|
||||
left: string;
|
||||
top: string;
|
||||
width: number;
|
||||
duration: number;
|
||||
}
|
||||
|
||||
export function InkDecoration({ variant = 'balanced', className = '' }: InkDecorationProps) {
|
||||
const [dropPositions, setDropPositions] = useState<DropPosition[]>([]);
|
||||
const [splashPositions, setSplashPositions] = useState<SplashPosition[]>([]);
|
||||
const [sealPositions, setSealPositions] = useState<SealPosition[]>([]);
|
||||
const [stainPositions, setStainPositions] = useState<StainPosition[]>([]);
|
||||
const [strokePositions, setStrokePositions] = useState<StrokePosition[]>([]);
|
||||
|
||||
const config = {
|
||||
minimal: { drops: 3, splashes: 1, seals: 1, stains: 1, strokes: 1 },
|
||||
@@ -366,53 +404,45 @@ export function InkDecoration({ variant = 'balanced', className = '' }: InkDecor
|
||||
|
||||
const { drops, splashes, seals, stains, strokes } = config[variant];
|
||||
|
||||
const dropPositions = useMemo(() => {
|
||||
if (!isMounted) return [];
|
||||
return Array.from({ length: drops }, (_, i) => ({
|
||||
useEffect(() => {
|
||||
setDropPositions(Array.from({ length: drops }, (_, i) => ({
|
||||
left: `${15 + (i * 70 / drops)}%`,
|
||||
top: `${20 + Math.random() * 60}%`,
|
||||
size: 6 + Math.random() * 14,
|
||||
opacity: 0.06 + Math.random() * 0.1,
|
||||
blur: Math.random() * 3,
|
||||
isRed: i % 3 === 0,
|
||||
}));
|
||||
}, [drops, isMounted]);
|
||||
|
||||
const splashPositions = useMemo(() => {
|
||||
if (!isMounted) return [];
|
||||
return Array.from({ length: splashes }, (_, i) => ({
|
||||
duration: 5 + Math.random() * 3,
|
||||
})));
|
||||
|
||||
setSplashPositions(Array.from({ length: splashes }, (_, i) => ({
|
||||
left: `${20 + (i * 60 / splashes)}%`,
|
||||
top: `${15 + Math.random() * 70}%`,
|
||||
size: 40 + Math.random() * 40,
|
||||
}));
|
||||
}, [splashes, isMounted]);
|
||||
|
||||
const sealPositions = useMemo(() => {
|
||||
if (!isMounted) return [];
|
||||
return Array.from({ length: seals }, (_, i) => ({
|
||||
duration: 7 + Math.random() * 3,
|
||||
})));
|
||||
|
||||
setSealPositions(Array.from({ length: seals }, (_, i) => ({
|
||||
left: `${25 + (i * 50 / seals)}%`,
|
||||
top: `${25 + Math.random() * 50}%`,
|
||||
size: 25 + Math.random() * 25,
|
||||
}));
|
||||
}, [seals, isMounted]);
|
||||
|
||||
const stainPositions = useMemo(() => {
|
||||
if (!isMounted) return [];
|
||||
return Array.from({ length: stains }, (_, i) => ({
|
||||
duration: 6 + Math.random() * 2,
|
||||
})));
|
||||
|
||||
setStainPositions(Array.from({ length: stains }, (_, i) => ({
|
||||
left: `${10 + (i * 80 / stains)}%`,
|
||||
top: `${30 + Math.random() * 40}%`,
|
||||
size: 80 + Math.random() * 60,
|
||||
}));
|
||||
}, [stains, isMounted]);
|
||||
|
||||
const strokePositions = useMemo(() => {
|
||||
if (!isMounted) return [];
|
||||
return Array.from({ length: strokes }, (_, i) => ({
|
||||
duration: 8 + Math.random() * 4,
|
||||
})));
|
||||
|
||||
setStrokePositions(Array.from({ length: strokes }, (_, i) => ({
|
||||
left: `${15 + (i * 70 / strokes)}%`,
|
||||
top: `${40 + Math.random() * 30}%`,
|
||||
width: 100 + Math.random() * 100,
|
||||
}));
|
||||
}, [strokes, isMounted]);
|
||||
duration: 6 + Math.random() * 3,
|
||||
})));
|
||||
}, [drops, splashes, seals, stains, strokes]);
|
||||
|
||||
return (
|
||||
<div className={`absolute inset-0 pointer-events-none overflow-hidden ${className}`}>
|
||||
@@ -426,7 +456,7 @@ export function InkDecoration({ variant = 'balanced', className = '' }: InkDecor
|
||||
scale: [1, 1.1, 1],
|
||||
}}
|
||||
transition={{
|
||||
duration: 5 + Math.random() * 3,
|
||||
duration: pos.duration,
|
||||
delay: i * 0.2,
|
||||
repeat: Infinity,
|
||||
ease: 'easeInOut',
|
||||
@@ -452,7 +482,7 @@ export function InkDecoration({ variant = 'balanced', className = '' }: InkDecor
|
||||
rotate: [0, 5, -5, 0],
|
||||
}}
|
||||
transition={{
|
||||
duration: 7 + Math.random() * 3,
|
||||
duration: pos.duration,
|
||||
delay: i * 0.3,
|
||||
repeat: Infinity,
|
||||
ease: 'easeInOut',
|
||||
@@ -472,7 +502,7 @@ export function InkDecoration({ variant = 'balanced', className = '' }: InkDecor
|
||||
rotate: [-8, -5, -10, -8],
|
||||
}}
|
||||
transition={{
|
||||
duration: 6 + Math.random() * 2,
|
||||
duration: pos.duration,
|
||||
delay: i * 0.25,
|
||||
repeat: Infinity,
|
||||
ease: 'easeInOut',
|
||||
@@ -492,7 +522,7 @@ export function InkDecoration({ variant = 'balanced', className = '' }: InkDecor
|
||||
opacity: [0.04, 0.06, 0.04],
|
||||
}}
|
||||
transition={{
|
||||
duration: 8 + Math.random() * 4,
|
||||
duration: pos.duration,
|
||||
delay: i * 0.35,
|
||||
repeat: Infinity,
|
||||
ease: 'easeInOut',
|
||||
@@ -512,7 +542,7 @@ export function InkDecoration({ variant = 'balanced', className = '' }: InkDecor
|
||||
opacity: [0.08, 0.12, 0.08],
|
||||
}}
|
||||
transition={{
|
||||
duration: 6 + Math.random() * 3,
|
||||
duration: pos.duration,
|
||||
delay: i * 0.3,
|
||||
repeat: Infinity,
|
||||
ease: 'easeInOut',
|
||||
|
||||
Reference in New Issue
Block a user