Added exclusion zone

This commit is contained in:
2025-03-24 23:56:27 -06:00
parent 4300aec72d
commit c96a592849
4 changed files with 29 additions and 12 deletions

View File

@ -41,11 +41,16 @@
.content { .content {
position: absolute; position: absolute;
width: calc(100vw / 0.01); /* Width based on minimum zoom (0.01) */ width: calc(100vw / 0.01); /* Width based on minimum zoom (0.01) */
height: calc(100vh / 0.01); /* Height based on minimum zoom (0.01) */ height: calc((100vh - 100px) / 0.01); /* Height based on minimum zoom minus UI height */
transform-origin: 0 0; transform-origin: 0 0;
background-color: white; background-color: white;
will-change: transform; will-change: transform;
contain: layout paint; contain: layout paint;
/* Add a subtle grid pattern to help with orientation */
background-image:
linear-gradient(rgba(200, 200, 200, 0.1) 1px, transparent 1px),
linear-gradient(90deg, rgba(200, 200, 200, 0.1) 1px, transparent 1px);
background-size: 50px 50px;
} }
.target { .target {

View File

@ -43,8 +43,8 @@ export interface Round {
export const CONSTANTS = { export const CONSTANTS = {
TARGET_COUNT: 200, TARGET_COUNT: 200,
TARGET_MIN_RADIUS: 20, TARGET_MIN_RADIUS: 100,
TARGET_MAX_RADIUS: 40, TARGET_MAX_RADIUS: 600,
VIRTUAL_CANVAS_SIZE: 50000, VIRTUAL_CANVAS_SIZE: 50000,
ZOOM_LEVELS: { ZOOM_LEVELS: {
min: 0.01, min: 0.01,

View File

@ -11,17 +11,23 @@ export const calculateZoomDelta = (
export const calculateInitialViewport = (initialZoom: number): ViewportOffset => { export const calculateInitialViewport = (initialZoom: number): ViewportOffset => {
// When fully zoomed out, we want to see the entire content area // When fully zoomed out, we want to see the entire content area
// The target distribution is sized to match the viewport at minimum zoom // The target distribution is sized to match the viewport at minimum zoom
// So at any higher zoom level, we need to position appropriately // Account for the UI exclusion zone at the top
const windowWidth = window.innerWidth; const windowWidth = window.innerWidth;
const windowHeight = window.innerHeight; const windowHeight = window.innerHeight;
// Same UI margin as in target generation
const UI_TOP_MARGIN = 100;
// Center the viewport on the target area // Center the viewport on the target area
const areaWidth = windowWidth / CONSTANTS.ZOOM_LEVELS.min; const areaWidth = windowWidth / CONSTANTS.ZOOM_LEVELS.min;
const areaHeight = windowHeight / CONSTANTS.ZOOM_LEVELS.min; const areaHeight = (windowHeight - UI_TOP_MARGIN) / CONSTANTS.ZOOM_LEVELS.min;
// Account for the UI exclusion zone in Y offset
const startY = UI_TOP_MARGIN / CONSTANTS.ZOOM_LEVELS.min;
return { return {
x: (areaWidth - windowWidth / initialZoom) / 2, x: (areaWidth - windowWidth / initialZoom) / 2,
y: (areaHeight - windowHeight / initialZoom) / 2 y: startY + (areaHeight - windowHeight / initialZoom) / 2
}; };
}; };

View File

@ -3,19 +3,25 @@ import { Target, CONSTANTS } from '../types';
export const generateTargets = () => { export const generateTargets = () => {
const newTargets: Target[] = []; const newTargets: Target[] = [];
// Fixed target size for better visibility // Use the constants from types.ts for consistency
const MIN_RADIUS = 100; const MIN_RADIUS = CONSTANTS.TARGET_MIN_RADIUS;
const MAX_RADIUS = 600; const MAX_RADIUS = CONSTANTS.TARGET_MAX_RADIUS;
// Get browser window dimensions // Get browser window dimensions
const windowWidth = window.innerWidth; const windowWidth = window.innerWidth;
const windowHeight = window.innerHeight; const windowHeight = window.innerHeight;
// Define UI exclusion zone (top area where UI elements are located)
const UI_TOP_MARGIN = 100; // pixels from top to exclude
// Base the target area on the minimum zoom level // Base the target area on the minimum zoom level
// This ensures when fully zoomed out, we see the entire grid // This ensures when fully zoomed out, we see the entire grid
const minZoom = CONSTANTS.ZOOM_LEVELS.min; const minZoom = CONSTANTS.ZOOM_LEVELS.min;
const areaWidth = windowWidth / minZoom; const areaWidth = windowWidth / minZoom;
const areaHeight = windowHeight / minZoom; const areaHeight = (windowHeight - UI_TOP_MARGIN) / minZoom;
// Start Y position below the UI elements
const startY = UI_TOP_MARGIN / minZoom;
// Create a grid-like distribution // Create a grid-like distribution
const gridSize = Math.ceil(Math.sqrt(CONSTANTS.TARGET_COUNT)); const gridSize = Math.ceil(Math.sqrt(CONSTANTS.TARGET_COUNT));
@ -31,9 +37,9 @@ export const generateTargets = () => {
const randomOffsetX = (Math.random() - 0.5) * cellWidth * 0.6; const randomOffsetX = (Math.random() - 0.5) * cellWidth * 0.6;
const randomOffsetY = (Math.random() - 0.5) * cellHeight * 0.6; const randomOffsetY = (Math.random() - 0.5) * cellHeight * 0.6;
// Calculate final position // Calculate final position - add startY to push everything down below UI
const x = cellWidth * (gridX + 0.5) + randomOffsetX; const x = cellWidth * (gridX + 0.5) + randomOffsetX;
const y = cellHeight * (gridY + 0.5) + randomOffsetY; const y = startY + cellHeight * (gridY + 0.5) + randomOffsetY;
// Random radius // Random radius
const radius = MIN_RADIUS + Math.random() * (MAX_RADIUS - MIN_RADIUS); const radius = MIN_RADIUS + Math.random() * (MAX_RADIUS - MIN_RADIUS);