* refactor: 编辑器/运行时架构拆分与构建系统升级 * feat(core): 层级系统重构与UI变换矩阵修复 * refactor: 移除 ecs-components 聚合包并修复跨包组件查找问题 * fix(physics): 修复跨包组件类引用问题 * feat: 统一运行时架构与浏览器运行支持 * feat(asset): 实现浏览器运行时资产加载系统 * fix: 修复文档、CodeQL安全问题和CI类型检查错误 * fix: 修复文档、CodeQL安全问题和CI类型检查错误 * fix: 修复文档、CodeQL安全问题、CI类型检查和测试错误 * test: 补齐核心模块测试用例,修复CI构建配置 * fix: 修复测试用例中的类型错误和断言问题 * fix: 修复 turbo build:npm 任务的依赖顺序问题 * fix: 修复 CI 构建错误并优化构建性能
128 lines
3.7 KiB
TypeScript
128 lines
3.7 KiB
TypeScript
import { React, useMemo } from '@esengine/editor-runtime';
|
||
|
||
interface GridBackgroundProps {
|
||
canvasOffset: { x: number; y: number };
|
||
canvasScale: number;
|
||
width: number;
|
||
height: number;
|
||
}
|
||
|
||
/**
|
||
* 编辑器网格背景
|
||
*/
|
||
export const GridBackground: React.FC<GridBackgroundProps> = ({
|
||
canvasOffset,
|
||
canvasScale,
|
||
width,
|
||
height
|
||
}) => {
|
||
const gridPattern = useMemo(() => {
|
||
// 基础网格大小(未缩放)
|
||
const baseGridSize = 20;
|
||
const baseDotSize = 1.5;
|
||
|
||
// 根据缩放级别调整网格大小
|
||
const gridSize = baseGridSize * canvasScale;
|
||
const dotSize = Math.max(baseDotSize, baseDotSize * canvasScale);
|
||
|
||
// 计算网格偏移(考虑画布偏移)
|
||
const offsetX = canvasOffset.x % gridSize;
|
||
const offsetY = canvasOffset.y % gridSize;
|
||
|
||
// 计算需要渲染的网格点数量
|
||
const cols = Math.ceil(width / gridSize) + 2;
|
||
const rows = Math.ceil(height / gridSize) + 2;
|
||
|
||
const dots: Array<{ x: number; y: number }> = [];
|
||
|
||
for (let i = -1; i < rows; i++) {
|
||
for (let j = -1; j < cols; j++) {
|
||
dots.push({
|
||
x: j * gridSize + offsetX,
|
||
y: i * gridSize + offsetY
|
||
});
|
||
}
|
||
}
|
||
|
||
return { dots, dotSize, gridSize };
|
||
}, [canvasOffset, canvasScale, width, height]);
|
||
|
||
// 大网格(每5个小格一个大格)
|
||
const majorGridPattern = useMemo(() => {
|
||
const majorGridSize = gridPattern.gridSize * 5;
|
||
const offsetX = canvasOffset.x % majorGridSize;
|
||
const offsetY = canvasOffset.y % majorGridSize;
|
||
|
||
const lines: Array<{ type: 'h' | 'v'; pos: number }> = [];
|
||
|
||
// 垂直线
|
||
const vCols = Math.ceil(width / majorGridSize) + 2;
|
||
for (let i = -1; i < vCols; i++) {
|
||
lines.push({
|
||
type: 'v',
|
||
pos: i * majorGridSize + offsetX
|
||
});
|
||
}
|
||
|
||
// 水平线
|
||
const hRows = Math.ceil(height / majorGridSize) + 2;
|
||
for (let i = -1; i < hRows; i++) {
|
||
lines.push({
|
||
type: 'h',
|
||
pos: i * majorGridSize + offsetY
|
||
});
|
||
}
|
||
|
||
return lines;
|
||
}, [canvasOffset, canvasScale, width, height, gridPattern.gridSize]);
|
||
|
||
return (
|
||
<svg
|
||
style={{
|
||
position: 'absolute',
|
||
top: 0,
|
||
left: 0,
|
||
width: '100%',
|
||
height: '100%',
|
||
pointerEvents: 'none'
|
||
}}
|
||
>
|
||
{/* 主网格线 */}
|
||
{majorGridPattern.map((line, idx) => (
|
||
line.type === 'v' ? (
|
||
<line
|
||
key={`v-${idx}`}
|
||
x1={line.pos}
|
||
y1={0}
|
||
x2={line.pos}
|
||
y2={height}
|
||
stroke="rgba(255, 255, 255, 0.03)"
|
||
strokeWidth="1"
|
||
/>
|
||
) : (
|
||
<line
|
||
key={`h-${idx}`}
|
||
x1={0}
|
||
y1={line.pos}
|
||
x2={width}
|
||
y2={line.pos}
|
||
stroke="rgba(255, 255, 255, 0.03)"
|
||
strokeWidth="1"
|
||
/>
|
||
)
|
||
))}
|
||
|
||
{/* 点阵网格 */}
|
||
{gridPattern.dots.map((dot, idx) => (
|
||
<circle
|
||
key={idx}
|
||
cx={dot.x}
|
||
cy={dot.y}
|
||
r={gridPattern.dotSize}
|
||
fill="rgba(255, 255, 255, 0.15)"
|
||
/>
|
||
))}
|
||
</svg>
|
||
);
|
||
};
|