fix: use screen pixels for zoom, abandon SVG path parsing
The calculateBoundingBox function doesn't handle relative SVG path commands correctly. Gibraltar's path uses 'm' (relative move) followed by tiny relative offsets like -0.009, 0.047, but the function treated them as absolute coordinates, giving width of 460 units instead of 0.08. Proper SVG path parsing requires: - Tracking current position as you iterate through commands - Handling both absolute (M,L,H,V,C,S,Q,T,A) and relative (m,l,h,v,c,s,q,t,a) - Curves need Bezier math to find actual bounds - Too complex for this use case Solution: Use screen pixels (getBoundingClientRect) for everything. Screen pixel measurements work correctly for tiny regions: - Gibraltar: 0.08px (accurate) - Jersey: 0.82px (accurate) New zoom formula for screen pixels: - Sub-pixel (< 1px): 1000/(size+0.05) - Gibraltar (0.08px): ~7692x → capped at 1000x - Tiny (1-10px): 500/(size+0.5) - 1px: ~333x - 5px: ~91x - Small (10-50px): Linear up to +50x 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
d72f309bad
commit
912dc385b3
|
|
@ -826,15 +826,13 @@ export function MapRenderer({
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track region sizes for adaptive zoom and dampening
|
// Track region sizes - use screen pixels for both zoom and dampening
|
||||||
// - SVG units (from viewBox) for accurate zoom calculation
|
// SVG path parsing is too complex (relative vs absolute commands)
|
||||||
// - Screen pixels (from getBoundingClientRect) for cursor dampening
|
// Screen pixels work well for tiny regions like Gibraltar (0.08px)
|
||||||
const svgBBox = calculateBoundingBox(region.path)
|
|
||||||
const svgSize = Math.min(svgBBox.width, svgBBox.height)
|
|
||||||
const screenSize = Math.min(pixelWidth, pixelHeight)
|
const screenSize = Math.min(pixelWidth, pixelHeight)
|
||||||
|
|
||||||
totalRegionArea += pixelArea
|
totalRegionArea += pixelArea
|
||||||
detectedSmallestSize = Math.min(detectedSmallestSize, svgSize)
|
detectedSmallestSize = Math.min(detectedSmallestSize, screenSize)
|
||||||
detectedSmallestScreenSize = Math.min(detectedSmallestScreenSize, screenSize)
|
detectedSmallestScreenSize = Math.min(detectedSmallestScreenSize, screenSize)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -861,16 +859,15 @@ export function MapRenderer({
|
||||||
|
|
||||||
// Debug logging - ONLY for Gibraltar or ultra-small regions
|
// Debug logging - ONLY for Gibraltar or ultra-small regions
|
||||||
const hasGibraltar = detectedRegions.includes('gi')
|
const hasGibraltar = detectedRegions.includes('gi')
|
||||||
if (hasGibraltar || detectedSmallestSize < 5) {
|
if (hasGibraltar || detectedSmallestSize < 1) {
|
||||||
console.log(
|
console.log(
|
||||||
`[Magnifier] ${hasGibraltar ? '🎯 GIBRALTAR DETECTED' : '🔍 Tiny region'} Detection:`,
|
`[Magnifier] ${hasGibraltar ? '🎯 GIBRALTAR DETECTED' : '🔍 Tiny region'} Detection:`,
|
||||||
{
|
{
|
||||||
detectedRegionIds: detectedRegions,
|
detectedRegionIds: detectedRegions,
|
||||||
regionsInBox,
|
regionsInBox,
|
||||||
smallestSvgSize: detectedSmallestSize.toFixed(4) + ' SVG units',
|
smallestScreenSize: detectedSmallestSize.toFixed(4) + 'px',
|
||||||
smallestScreenSize: detectedSmallestScreenSize.toFixed(2) + 'px',
|
|
||||||
shouldShow,
|
shouldShow,
|
||||||
movementMultiplier: getMovementMultiplier(detectedSmallestScreenSize).toFixed(2),
|
movementMultiplier: getMovementMultiplier(detectedSmallestSize).toFixed(2),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -885,21 +882,25 @@ export function MapRenderer({
|
||||||
adaptiveZoom += countFactor * 20 // Up to +20x for density
|
adaptiveZoom += countFactor * 20 // Up to +20x for density
|
||||||
|
|
||||||
// Add zoom based on smallest region size (tiny regions need EXTREME zoom)
|
// Add zoom based on smallest region size (tiny regions need EXTREME zoom)
|
||||||
// Note: detectedSmallestSize is now in SVG viewBox units (0-1010), not screen pixels
|
// detectedSmallestSize is in screen pixels (from getBoundingClientRect)
|
||||||
// Gibraltar is ~0.08 SVG units, most countries are 10-100 SVG units
|
// Gibraltar is ~0.08px, most countries are 10-100px
|
||||||
let sizeZoom = 0
|
let sizeZoom = 0
|
||||||
if (detectedSmallestSize !== Infinity) {
|
if (detectedSmallestSize !== Infinity) {
|
||||||
// For Gibraltar (0.08 SVG units): we need massive zoom
|
// For Gibraltar (0.08px): we need massive zoom
|
||||||
// Use exponential scaling for tiny regions
|
// Use exponential scaling for sub-pixel and tiny regions
|
||||||
if (detectedSmallestSize < 5) {
|
if (detectedSmallestSize < 1) {
|
||||||
// Tiny regions (< 5 SVG units) get exponential zoom
|
// Sub-pixel regions get extreme zoom
|
||||||
// Gibraltar (0.08): 200/(0.08+0.1) ≈ 1111x → capped at 1000x
|
// Gibraltar (0.08px): 1000/(0.08+0.05) ≈ 7692x → capped at 1000x
|
||||||
// 1 SVG unit: 200/(1+0.1) ≈ 182x
|
sizeZoom = 1000 / (detectedSmallestSize + 0.05)
|
||||||
// 5 SVG units: 200/(5+0.1) ≈ 39x
|
} else if (detectedSmallestSize < 10) {
|
||||||
sizeZoom = 200 / (detectedSmallestSize + 0.1)
|
// Very small regions (1-10px) get high zoom
|
||||||
|
// 1px: 500/(1+0.5) ≈ 333x
|
||||||
|
// 5px: 500/(5+0.5) ≈ 91x
|
||||||
|
// 10px: 500/(10+0.5) ≈ 48x
|
||||||
|
sizeZoom = 500 / (detectedSmallestSize + 0.5)
|
||||||
} else {
|
} else {
|
||||||
// Regular small regions use linear scaling
|
// Regular small regions use linear scaling
|
||||||
const sizeFactor = Math.max(0, 1 - detectedSmallestSize / 100) // 0 to 1
|
const sizeFactor = Math.max(0, 1 - detectedSmallestSize / 50) // 0 to 1
|
||||||
sizeZoom = sizeFactor * 50 // Up to +50x for small regions
|
sizeZoom = sizeFactor * 50 // Up to +50x for small regions
|
||||||
}
|
}
|
||||||
adaptiveZoom += sizeZoom
|
adaptiveZoom += sizeZoom
|
||||||
|
|
@ -912,8 +913,7 @@ export function MapRenderer({
|
||||||
// Debug logging for Gibraltar - show full calculation breakdown
|
// Debug logging for Gibraltar - show full calculation breakdown
|
||||||
if (hasGibraltar) {
|
if (hasGibraltar) {
|
||||||
console.log(`[Zoom] 🎯 GIBRALTAR BREAKDOWN:`, {
|
console.log(`[Zoom] 🎯 GIBRALTAR BREAKDOWN:`, {
|
||||||
regionSize: `${detectedSmallestSize.toFixed(6)} SVG units`,
|
regionSize: `${detectedSmallestSize.toFixed(6)}px (screen)`,
|
||||||
viewBoxSize: '1010 × 666',
|
|
||||||
baseZoom: 10,
|
baseZoom: 10,
|
||||||
densityZoom: (countFactor * 20).toFixed(1),
|
densityZoom: (countFactor * 20).toFixed(1),
|
||||||
sizeZoom: sizeZoom.toFixed(1),
|
sizeZoom: sizeZoom.toFixed(1),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue