mirror of
https://github.com/MoonTechLab/LunaTV.git
synced 2026-02-27 23:34:48 +08:00
feat(components): 优化卡片组件交互效果与动画
重构 AggregateCard、DemoCard 和 VideoCard 组件的交互效果: 1. 统一卡片悬停动画,使用 cubic-bezier 实现平滑过渡 2. 改进播放按钮和收藏按钮的视觉反馈 3. 优化集数显示样式为矩形框 4. 添加卡片删除时的淡出动画 5. 统一外部链接按钮样式 6. 调整标题悬停效果和位置
This commit is contained in:
@@ -25,8 +25,7 @@ function SearchCircle({
|
||||
viewBox='0 0 44 44'
|
||||
fill='none'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
className={className}
|
||||
style={{ display: 'block' }}
|
||||
className={`${className} block relative`}
|
||||
>
|
||||
<circle
|
||||
cx='22'
|
||||
@@ -36,21 +35,11 @@ function SearchCircle({
|
||||
strokeWidth='1.5'
|
||||
fill={fillColor}
|
||||
/>
|
||||
<g>
|
||||
<foreignObject x='12' y='12' width='20' height='20'>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
<Search className='h-7 w-7 text-white' strokeWidth={2} />
|
||||
</div>
|
||||
</foreignObject>
|
||||
</g>
|
||||
<foreignObject x='0' y='0' width='44' height='44'>
|
||||
<div className='w-full h-full flex items-center justify-center'>
|
||||
<Search className='h-7 w-7 text-white' strokeWidth={2} />
|
||||
</div>
|
||||
</foreignObject>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -65,62 +54,60 @@ const DemoCard = ({ id, title, poster, rate, type }: DemoCardProps) => {
|
||||
|
||||
return (
|
||||
<div
|
||||
className='group relative w-full rounded-lg bg-transparent shadow-none flex flex-col cursor-pointer'
|
||||
className='group relative w-full rounded-lg bg-transparent flex flex-col cursor-pointer transition-all duration-500 ease-in-out'
|
||||
onClick={handleClick}
|
||||
>
|
||||
{/* 海报图片 - 2:3 比例 */}
|
||||
<div className='relative aspect-[2/3] w-full overflow-hidden rounded-md'>
|
||||
{/* 海报图片区域 */}
|
||||
<div className='relative aspect-[2/3] w-full overflow-hidden rounded-md group-hover:scale-[1.02] transition-all duration-700 cubic-bezier(0.4, 0, 0.2, 1)'>
|
||||
<Image
|
||||
src={poster}
|
||||
alt={title}
|
||||
fill
|
||||
className='object-cover'
|
||||
className='object-cover transition-transform duration-1000 cubic-bezier(0.4, 0, 0.2, 1) group-hover:scale-110'
|
||||
referrerPolicy='no-referrer'
|
||||
unoptimized
|
||||
priority={false}
|
||||
/>
|
||||
|
||||
{/* 评分徽章 */}
|
||||
{rate && (
|
||||
<div className='absolute top-2 right-2 min-w-[1.25rem] h-4 w-4 sm:h-7 sm:w-7 sm:min-w-[1.5rem] bg-pink-500 rounded-full flex items-center justify-center px-1'>
|
||||
<div className='absolute top-2 right-2 min-w-[1.25rem] h-4 w-4 sm:h-7 sm:w-7 sm:min-w-[1.5rem] bg-pink-500 rounded-full flex items-center justify-center px-1 shadow-md transform transition-all duration-500 cubic-bezier(0.4, 0, 0.2, 1) group-hover:scale-110 group-hover:rotate-3'>
|
||||
<span className='text-white text-[0.5rem] sm:text-xs font-bold leading-none'>
|
||||
{rate}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{/* Hover 效果 */}
|
||||
<div className='absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100 transition-opacity duration-200 flex items-center justify-center group'>
|
||||
<div className='absolute inset-0 flex items-center justify-center'>
|
||||
<div
|
||||
onMouseEnter={() => setHover(true)}
|
||||
onMouseLeave={() => setHover(false)}
|
||||
className={`transition-all duration-200 ${
|
||||
hover ? 'scale-110' : ''
|
||||
}`}
|
||||
>
|
||||
<SearchCircle fillColor={hover ? '#22c55e' : 'none'} />
|
||||
</div>
|
||||
|
||||
{/* 悬浮层 - 搜索按钮 */}
|
||||
<div className='absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent opacity-0 group-hover:opacity-100 transition-all duration-500 cubic-bezier(0.4, 0, 0.2, 1) flex items-center justify-center'>
|
||||
<div
|
||||
onMouseEnter={() => setHover(true)}
|
||||
onMouseLeave={() => setHover(false)}
|
||||
className={`transition-all duration-500 cubic-bezier(0.4, 0, 0.2, 1) ${
|
||||
hover ? 'scale-110 rotate-12' : 'scale-90'
|
||||
}`}
|
||||
>
|
||||
<SearchCircle fillColor={hover ? '#22c55e' : 'none'} />
|
||||
</div>
|
||||
</div>
|
||||
{/* 顶部左侧 🔗 链接按钮 */}
|
||||
|
||||
{/* 外部链接按钮 */}
|
||||
<a
|
||||
href={`https://movie.douban.com/subject/${id}`}
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className='absolute top-2 left-2 opacity-0 group-hover:opacity-100 transition-opacity duration-200'
|
||||
className='absolute top-2 left-2 scale-90 group-hover:scale-100 opacity-0 group-hover:opacity-100 transition-all duration-500 cubic-bezier(0.4, 0, 0.2, 1)'
|
||||
>
|
||||
<div className='w-4 h-4 sm:w-7 sm:h-7 rounded-full bg-green-500 flex items-center justify-center transition-all duration-200 hover:scale-110'>
|
||||
<div className='w-4 h-4 sm:w-7 sm:h-7 rounded-full bg-[#22c55e] flex items-center justify-center shadow-md opacity-70 hover:opacity-100 transition-all duration-300 ease-in-out hover:scale-110 hover:bg-[#16a34a]'>
|
||||
<LinkIcon className='w-4 h-4 text-white' strokeWidth={2} />
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* 信息层 */}
|
||||
<div className='absolute top-[calc(100%+0.2rem)] left-0 right-0'>
|
||||
<div className='flex flex-col items-center justify-center'>
|
||||
<span className='text-gray-900 font-semibold truncate w-full text-center text-xs sm:text-sm dark:text-gray-200'>
|
||||
{title}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<span className='mt-2 px-1 block text-gray-900 font-semibold truncate w-full text-center text-xs sm:text-sm dark:text-gray-200 transition-all duration-700 cubic-bezier(0.4, 0, 0.2, 1) group-hover:translate-y-[-2px] translate-y-1 opacity-80 group-hover:opacity-100 group-hover:text-green-600 dark:group-hover:text-green-400'>
|
||||
{title}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user