Files
shanghai-residences/src/components/layout/ScaledPortal.tsx
T
zhongyidian 45dd648d21 feat: 清理无用的 MacOS 文件和更新组件,提升代码整洁性
- 删除多个无用的 MacOS 生成文件,减少项目冗余。
- 在 layout 组件中添加 ScaledPortal 和相关类型,增强组件功能。
- 更新 puzzleData 中的学校名称,确保信息准确性。
- 调整 internalization 组件中的提示文本,提升用户体验。
- 在多个场景中引入新的选择题和成功提示,增强学习互动性。
2026-02-01 14:37:14 +08:00

60 lines
1.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { ReactNode } from "react";
import { useEffect, useState } from "react";
import { createPortal } from "react-dom";
import { useScale } from "@/contexts/ScaleContext";
export interface ScaledPortalProps {
/** 是否启用(不启用则直接渲染 children) */
enabled?: boolean;
/** z-index 层级(建议 > ExhibitOverlay 的 9999) */
zIndex?: number;
/** 子元素 */
children: ReactNode;
}
/**
* ScaledPortal
* - 使用 Portal 渲染到 document.body,避免被其他 Portal/遮罩层挡住
* - 使用 useScale 的 offset/scale 做视觉对齐(与 ExhibitOverlay 一致)
*/
const ScaledPortal = ({
enabled = true,
zIndex = 10050,
children,
}: ScaledPortalProps) => {
const [mounted, setMounted] = useState(false);
const { scale, offsetX, offsetY, DESIGN_WIDTH, DESIGN_HEIGHT } = useScale();
useEffect(() => {
setMounted(true);
}, []);
if (!enabled) return <>{children}</>;
if (!mounted) return null;
const scaled = (
<div
style={{
position: "fixed",
inset: 0,
width: `${DESIGN_WIDTH}px`,
height: `${DESIGN_HEIGHT}px`,
left: `${offsetX}px`,
top: `${offsetY}px`,
transform: `scale(${scale})`,
transformOrigin: "top left",
pointerEvents: "auto",
zIndex,
}}
>
{children}
</div>
);
return createPortal(scaled, document.body);
};
export default ScaledPortal;