- 在 .gitignore 中添加 public/audio/* 以忽略音频文件。 - 更新 bun.lock,添加 eslint-config-prettier 和 eslint-plugin-prettier 依赖,确保 ESLint 与 Prettier 的兼容性。 - 修改 eslint.config.ts,整合 Prettier 规则,优化代码风格一致性。 - 在 package.json 中添加 lint:fix 和 format 脚本,简化代码格式化和修复流程。 - 更新 tailwind.config.ts 和其他组件文件,统一代码风格,提升可读性。
54 lines
1.4 KiB
TypeScript
54 lines
1.4 KiB
TypeScript
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
|