feat: 更新组件和引导对话,增强用户体验
- 在多个组件中添加新的选择和填空功能,提升互动性。 - 更新引导对话文本,确保信息准确性和一致性。 - 引入新的选择组件,优化用户填写体验。 - 清理冗余代码,提升可维护性。
This commit is contained in:
1 parent
a8723ab4aa
commit
5bdfdadede
27 files changed
+880
-1252
No files matched your search
@@ -41,11 +41,7 @@ const PuzzlePieceDisplay = forwardRef<HTMLDivElement, PuzzlePieceDisplayProps>(
|
||||
}
|
||||
}
|
||||
`}</style>
|
||||
<img
|
||||
src={pieceImage}
|
||||
alt={`碎片 ${pieceId}`}
|
||||
className="w-full h-full object-contain"
|
||||
/>
|
||||
<img src={pieceImage} alt={`碎片 ${pieceId}`} className="w-full" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -54,4 +50,3 @@ const PuzzlePieceDisplay = forwardRef<HTMLDivElement, PuzzlePieceDisplayProps>(
|
||||
PuzzlePieceDisplay.displayName = "PuzzlePieceDisplay";
|
||||
|
||||
export default PuzzlePieceDisplay;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { forwardRef } from "react";
|
||||
import { forwardRef, useEffect, useState } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { motion } from "framer-motion";
|
||||
import PuzzlePieceDisplay from "./PuzzlePieceDisplay";
|
||||
|
||||
interface PuzzlePiecePortalProps {
|
||||
@@ -12,21 +13,82 @@ interface PuzzlePiecePortalProps {
|
||||
/**
|
||||
* 碎片 Portal 组件
|
||||
* 将碎片渲染到 document.body,确保在最上层显示
|
||||
* 支持旋转+放大的初始出现动画
|
||||
*/
|
||||
const PuzzlePiecePortal = forwardRef<HTMLDivElement, PuzzlePiecePortalProps>(
|
||||
({ residence, pieceId, hidden = false }, ref) => {
|
||||
const [isAnimating, setIsAnimating] = useState(true);
|
||||
|
||||
// 当组件首次渲染时,标记动画开始
|
||||
useEffect(() => {
|
||||
setIsAnimating(true);
|
||||
// 动画完成后,重置状态以便下次出现时重新播放
|
||||
const timer = setTimeout(() => {
|
||||
setIsAnimating(false);
|
||||
}, 800); // 与动画时长一致
|
||||
return () => clearTimeout(timer);
|
||||
}, [pieceId]); // 当 pieceId 变化时重新播放动画
|
||||
|
||||
return createPortal(
|
||||
<div
|
||||
ref={ref}
|
||||
className="fixed z-[99999] pointer-events-none"
|
||||
style={{
|
||||
position: "fixed",
|
||||
left: "50%",
|
||||
top: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: "120px",
|
||||
height: "120px",
|
||||
opacity: hidden ? 0 : 1,
|
||||
visibility: hidden ? "hidden" : "visible",
|
||||
transform: "translate(-50%, -50%)",
|
||||
perspective: "1000px", // 添加透视,让3D效果更明显
|
||||
zIndex: 99999,
|
||||
pointerEvents: "none",
|
||||
}}
|
||||
>
|
||||
<motion.div
|
||||
ref={ref}
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
transformStyle: "preserve-3d", // 保持3D变换
|
||||
}}
|
||||
initial={
|
||||
isAnimating
|
||||
? {
|
||||
scale: 0,
|
||||
rotateY: -180,
|
||||
opacity: 0,
|
||||
}
|
||||
: false
|
||||
}
|
||||
animate={
|
||||
hidden
|
||||
? { opacity: 0, visibility: "hidden" as const }
|
||||
: isAnimating
|
||||
? {
|
||||
scale: 1,
|
||||
rotateY: 0,
|
||||
opacity: 1,
|
||||
visibility: "visible" as const,
|
||||
}
|
||||
: {
|
||||
opacity: 1,
|
||||
visibility: "visible" as const,
|
||||
}
|
||||
}
|
||||
transition={{
|
||||
duration: 0.8, // 稍微延长动画时间,让效果更舒缓
|
||||
ease: [0.25, 0.46, 0.45, 0.94], // 平滑的缓动函数,缓缓出现
|
||||
scale: {
|
||||
duration: 0.8,
|
||||
ease: [0.25, 0.46, 0.45, 0.94],
|
||||
},
|
||||
rotateY: {
|
||||
duration: 0.8,
|
||||
ease: [0.25, 0.46, 0.45, 0.94],
|
||||
},
|
||||
opacity: {
|
||||
duration: 0.6,
|
||||
ease: "easeOut",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<PuzzlePieceDisplay
|
||||
@@ -35,6 +97,7 @@ const PuzzlePiecePortal = forwardRef<HTMLDivElement, PuzzlePiecePortalProps>(
|
||||
showGlow={true}
|
||||
className="w-full h-full"
|
||||
/>
|
||||
</motion.div>
|
||||
</div>,
|
||||
document.body
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user