All files / web/src/arcade-games/know-your-world/utils magnifierDimensions.ts

51.11% Statements 46/90
100% Branches 0/0
0% Functions 0/3
51.11% Lines 46/90

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 911x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x             1x 1x 1x 1x 1x 1x           1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                                                                    
/**
 * Magnifier Dimension Utilities
 *
 * Shared functions for calculating magnifier dimensions that respond to
 * container aspect ratio. Used by MapRenderer and useMagnifierZoom.
 */
 
// Magnifier size ratios - responsive to container aspect ratio
export const MAGNIFIER_SIZE_SMALL = 1 / 3 // Used for the constrained dimension
export const MAGNIFIER_SIZE_LARGE = 1 / 2 // Used for the unconstrained dimension
 
// Margin around expanded magnifier (allows clicking outside to dismiss)
export const EXPANDED_MAGNIFIER_MARGIN = 20 // pixels
 
/**
 * Calculate magnifier dimensions based on container aspect ratio.
 * - Landscape (wider): 1/3 width, 1/2 height (more vertical space available)
 * - Portrait (taller): 1/2 width, 1/3 height (more horizontal space available)
 */
export function getMagnifierDimensions(containerWidth: number, containerHeight: number) {
  const isLandscape = containerWidth > containerHeight
  return {
    width: containerWidth * (isLandscape ? MAGNIFIER_SIZE_SMALL : MAGNIFIER_SIZE_LARGE),
    height: containerHeight * (isLandscape ? MAGNIFIER_SIZE_LARGE : MAGNIFIER_SIZE_SMALL),
  }
}
 
/**
 * Calculate expanded magnifier dimensions (fills leftover area minus margin).
 * The margin allows clicking outside the magnifier to dismiss it.
 */
export function getExpandedMagnifierDimensions(leftoverWidth: number, leftoverHeight: number) {
  return {
    width: leftoverWidth - EXPANDED_MAGNIFIER_MARGIN * 2,
    height: leftoverHeight - EXPANDED_MAGNIFIER_MARGIN * 2,
  }
}
 
/**
 * Calculate the magnified viewBox dimensions that match the magnifier container's aspect ratio.
 *
 * The magnifier container has a responsive aspect ratio (varies with screen orientation),
 * but the map viewBox has a fixed aspect ratio (e.g., 2:1 for world map). Without adjustment,
 * this causes letterboxing in the magnifier SVG.
 *
 * This function expands the viewBox dimensions to match the container's aspect ratio,
 * eliminating letterboxing and ensuring the outline on the main map matches exactly
 * what's visible in the magnifier.
 *
 * @param viewBoxWidth - The map's viewBox width
 * @param viewBoxHeight - The map's viewBox height
 * @param zoom - Current zoom level
 * @param containerWidth - The game container's width in pixels
 * @param containerHeight - The game container's height in pixels
 * @returns Adjusted width and height for the magnified viewBox
 */
export function getAdjustedMagnifiedDimensions(
  viewBoxWidth: number,
  viewBoxHeight: number,
  zoom: number,
  containerWidth: number,
  containerHeight: number
) {
  const { width: magWidth, height: magHeight } = getMagnifierDimensions(
    containerWidth,
    containerHeight
  )

  // Base dimensions from zoom (what we'd show without aspect ratio adjustment)
  const baseWidth = viewBoxWidth / zoom
  const baseHeight = viewBoxHeight / zoom

  // Compare aspect ratios
  const containerAspect = magWidth / magHeight
  const viewBoxAspect = baseWidth / baseHeight

  if (containerAspect > viewBoxAspect) {
    // Container is wider than viewBox aspect ratio - expand width to fill
    return {
      width: baseHeight * containerAspect,
      height: baseHeight,
    }
  } else {
    // Container is taller than viewBox aspect ratio - expand height to fill
    return {
      width: baseWidth,
      height: baseWidth / containerAspect,
    }
  }
}