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

0% Statements 0/90
0% Branches 0/1
0% Functions 0/1
0% Lines 0/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 91                                                                                                                                                                                     
/**
 * 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,
    }
  }
}