- 更新展品图片(鲁迅/毛泽东/孙中山/黄炎培/聂耳/张乐平故居) - 新增点击查看图标、报纸素材 - 优化视频组件、拼图组件、展品组件 - 更新陈云音频资源 - 新增输入验证文档和工具函数 - 组件布局和动画优化 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
59 lines
1.8 KiB
TypeScript
59 lines
1.8 KiB
TypeScript
import { forwardRef } from 'react'
|
|
import { getStaticImage } from '@/lib/utils'
|
|
|
|
export interface PuzzlePieceDisplayProps {
|
|
/** 故居名称,如 'chenyun' */
|
|
residence: string
|
|
/** 碎片ID */
|
|
pieceId: number
|
|
/** 是否显示发光动画 */
|
|
showGlow?: boolean
|
|
/** 在容器内按真实比例等比贴边展示 */
|
|
fitContain?: boolean
|
|
/** 自定义类名 */
|
|
className?: string
|
|
}
|
|
|
|
/**
|
|
* 拼图碎片显示组件
|
|
* - 显示碎片图片
|
|
* - 支持发光动画效果
|
|
* - 可以被 ref 引用,用于飞行动画
|
|
*/
|
|
const PuzzlePieceDisplay = forwardRef<HTMLDivElement, PuzzlePieceDisplayProps>(
|
|
({ residence, pieceId, showGlow = true, fitContain = false, className = '' }, ref) => {
|
|
// 碎片图片路径
|
|
const pieceImage = getStaticImage(`puzzle/${residence}/${pieceId}`)
|
|
|
|
return (
|
|
<div
|
|
ref={ref}
|
|
className={`relative ${fitContain ? 'h-full w-full overflow-visible' : 'inline-block'} ${className}`}
|
|
style={{
|
|
animation: showGlow ? 'puzzleGlow 1s ease-in-out infinite' : 'none',
|
|
}}
|
|
>
|
|
<style>{`
|
|
@keyframes puzzleGlow {
|
|
0%, 100% {
|
|
filter: drop-shadow(0 0 8px rgba(255, 255, 255, 0.8)) drop-shadow(0 0 16px rgba(255, 255, 255, 0.6));
|
|
}
|
|
50% {
|
|
filter: drop-shadow(0 0 16px rgba(255, 255, 255, 1)) drop-shadow(0 0 32px rgba(255, 255, 255, 0.8)) drop-shadow(0 0 48px rgba(255, 255, 255, 0.6));
|
|
}
|
|
}
|
|
`}</style>
|
|
<img
|
|
src={pieceImage}
|
|
alt={`碎片 ${pieceId}`}
|
|
className={fitContain ? 'absolute inset-0 block h-full w-full object-contain' : 'w-full'}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|
|
)
|
|
|
|
PuzzlePieceDisplay.displayName = 'PuzzlePieceDisplay'
|
|
|
|
export default PuzzlePieceDisplay
|