Files
NapCatQQ/packages/napcat-webui-frontend/src/components/effect_card.tsx
手瓜一十雪 4fcbdc4d89 Remove music player and related context/hooks
Deleted the audio player component, songs context, and use-music hook, along with all related code and configuration. Updated affected components and pages to remove music player dependencies and UI. Also improved sidebar, background, and about page UI, and refactored site config icons to use react-icons.
2025-12-20 18:07:16 +08:00

110 lines
3.1 KiB
TypeScript

import { Card, CardProps } from '@heroui/card';
import clsx from 'clsx';
import React from 'react';
export interface HoverEffectCardProps extends CardProps {
children: React.ReactNode
maxXRotation?: number
maxYRotation?: number
lightClassName?: string
lightStyle?: React.CSSProperties
}
const HoverEffectCard: React.FC<HoverEffectCardProps> = (props) => {
const {
children,
maxXRotation = 5,
maxYRotation = 5,
className,
style,
lightClassName,
lightStyle,
} = props;
const cardRef = React.useRef<HTMLDivElement | null>(null);
const lightRef = React.useRef<HTMLDivElement | null>(null);
const [isShowLight, setIsShowLight] = React.useState(false);
const [pos, setPos] = React.useState({
left: 0,
top: 0,
});
return (
<Card
{...props}
ref={cardRef}
className={clsx(
'relative overflow-hidden bg-opacity-50 backdrop-blur-lg',
className
)}
style={{
willChange: 'transform',
transform:
'perspective(1000px) rotateX(0deg) rotateY(0deg) scale3d(1, 1, 1)',
...style,
}}
onMouseEnter={() => {
if (cardRef.current) {
cardRef.current.style.transition = 'transform 0.3s ease-out';
}
}}
onMouseLeave={() => {
setIsShowLight(false);
if (cardRef.current) {
cardRef.current.style.transition = 'transform 0.5s';
cardRef.current.style.transform =
'perspective(1000px) rotateX(0deg) rotateY(0deg) scale3d(1, 1, 1)';
}
}}
onMouseMove={(e: React.MouseEvent<HTMLDivElement>) => {
if (cardRef.current) {
setIsShowLight(true);
const { x, y } = cardRef.current.getBoundingClientRect();
const { clientX, clientY } = e;
const offsetX = clientX - x;
const offsetY = clientY - y;
const lightWidth = lightStyle?.width?.toString() || '100';
const lightHeight = lightStyle?.height?.toString() || '100';
const lightWidthNum = parseInt(lightWidth);
const lightHeightNum = parseInt(lightHeight);
const left = offsetX - lightWidthNum / 2;
const top = offsetY - lightHeightNum / 2;
setPos({
left,
top,
});
cardRef.current.style.transition = 'transform 0.1s';
const rangeX = 400 / 2;
const rangeY = 400 / 2;
const rotateX = ((offsetY - rangeY) / rangeY) * maxXRotation;
const rotateY = -1 * ((offsetX - rangeX) / rangeX) * maxYRotation;
cardRef.current.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
}
}}
>
<div
ref={lightRef}
className={clsx(
isShowLight ? 'opacity-100' : 'opacity-0',
'absolute rounded-full blur-[100px] filter transition-opacity duration-300 bg-gradient-to-r from-primary-400 to-secondary-400 w-[150px] h-[150px]',
lightClassName
)}
style={{
...pos,
}}
/>
{children}
</Card>
);
};
export default HoverEffectCard;