- 在 .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 和其他组件文件,统一代码风格,提升可读性。
122 lines
2.9 KiB
TypeScript
122 lines
2.9 KiB
TypeScript
/**
|
|
* 计算阻止点击的区域(分成多个矩形块)
|
|
* 用于 Spotlight 和 Overlay 组件
|
|
*/
|
|
export interface BlockingDiv {
|
|
top: number
|
|
left: number
|
|
width: string | number
|
|
height: string | number
|
|
}
|
|
|
|
export interface Rect {
|
|
top: number
|
|
left: number
|
|
width: number
|
|
height: number
|
|
}
|
|
|
|
/**
|
|
* 根据高亮区域计算需要阻止点击的 div 块
|
|
* @param rects 高亮区域的矩形列表(视口坐标)
|
|
* @param viewportWidth 视口宽度
|
|
* @param viewportHeight 视口高度
|
|
* @returns 阻止点击的 div 块列表
|
|
*/
|
|
export function getBlockingDivs(
|
|
rects: Rect[],
|
|
viewportWidth: number,
|
|
viewportHeight: number
|
|
): BlockingDiv[] {
|
|
if (rects.length === 0) return []
|
|
|
|
const blocks: BlockingDiv[] = []
|
|
|
|
// 找出所有孔的边界
|
|
const minTop = Math.min(...rects.map((r) => r.top))
|
|
const maxBottom = Math.max(...rects.map((r) => r.top + r.height))
|
|
const minLeft = Math.min(...rects.map((r) => r.left))
|
|
const maxRight = Math.max(...rects.map((r) => r.left + r.width))
|
|
|
|
// 顶部大块
|
|
if (minTop > 0) {
|
|
blocks.push({
|
|
top: 0,
|
|
left: 0,
|
|
width: '100%',
|
|
height: minTop,
|
|
})
|
|
}
|
|
|
|
// 底部大块
|
|
if (maxBottom < viewportHeight) {
|
|
blocks.push({
|
|
top: maxBottom,
|
|
left: 0,
|
|
width: '100%',
|
|
height: viewportHeight - maxBottom,
|
|
})
|
|
}
|
|
|
|
// 左侧大块(中间部分)
|
|
if (minLeft > 0) {
|
|
blocks.push({
|
|
top: minTop,
|
|
left: 0,
|
|
width: minLeft,
|
|
height: maxBottom - minTop,
|
|
})
|
|
}
|
|
|
|
// 右侧大块(中间部分)
|
|
if (maxRight < viewportWidth) {
|
|
blocks.push({
|
|
top: minTop,
|
|
left: maxRight,
|
|
width: viewportWidth - maxRight,
|
|
height: maxBottom - minTop,
|
|
})
|
|
}
|
|
|
|
// 对于多个孔的情况,填充孔之间的间隙
|
|
if (rects.length > 1) {
|
|
// 按位置排序
|
|
const sortedByTop = [...rects].sort((a, b) => a.top - b.top)
|
|
const sortedByLeft = [...rects].sort((a, b) => a.left - b.left)
|
|
|
|
// 填充垂直间隙
|
|
for (let i = 0; i < sortedByTop.length - 1; i++) {
|
|
const current = sortedByTop[i]!
|
|
const next = sortedByTop[i + 1]!
|
|
const gap = next.top - (current.top + current.height)
|
|
|
|
if (gap > 0) {
|
|
blocks.push({
|
|
top: current.top + current.height,
|
|
left: Math.max(current.left, next.left),
|
|
width: Math.min(current.width, next.width),
|
|
height: gap,
|
|
})
|
|
}
|
|
}
|
|
|
|
// 填充水平间隙
|
|
for (let i = 0; i < sortedByLeft.length - 1; i++) {
|
|
const current = sortedByLeft[i]!
|
|
const next = sortedByLeft[i + 1]!
|
|
const gap = next.left - (current.left + current.width)
|
|
|
|
if (gap > 0) {
|
|
blocks.push({
|
|
top: Math.max(current.top, next.top),
|
|
left: current.left + current.width,
|
|
width: gap,
|
|
height: Math.min(current.height, next.height),
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
return blocks
|
|
}
|