NeighborhoodLabels class manages level-of-detail (LOD) neighborhood labels displayed on the OpenSeadragon map. It renders borough, major neighborhood, and NTA (Neighborhood Tabulation Area) labels based on the current zoom level.
Overview
NeighborhoodLabels avoids OpenSeadragon’s built-in overlay system (which wraps every element in a container and calls drawHTML() every frame). Instead, it uses a single absolutely-positioned container div and manually positions each label using viewport.pixelFromPoint() on the ‘update-viewport’ event.
Class Definition
Constructor
The OpenSeadragon viewer instance to attach labels to
src/NeighborhoodLabels.ts:55-78):
- Creates a container
<div>with absolute positioning andz-index: 80 - Appends container to the viewer element
- Calls
buildLabels()to create all label elements - Registers event handlers:
update-viewport→ callsdraw()to reposition labelszoom→ callsupdateTier()to show/hide labels based on zoom levelpan→ callsdraw()to reposition labels
- Calls
updateTier()to set initial visibility
Public Methods
setEnabled
true to show labels, false to hide themcontainer.style.display = 'none'. When re-enabled, resets the current tier to force a refresh and calls updateTier().
See implementation at src/NeighborhoodLabels.ts:80-84.
destroy
- Cancels any active
requestAnimationFramecallback (ifrafIdis set) - Removes the container element from the DOM
src/NeighborhoodLabels.ts:156-159.
Private Methods
buildLabels
-
Borough labels (5 total):
- MANHATTAN, BROOKLYN, QUEENS, BRONX, STATEN ISLAND
- Hardcoded centroids at
src/NeighborhoodLabels.ts:22-28
-
NTA labels (197 total):
- Loaded from
nta_centroids.json - Classified as ‘major’ (40 neighborhoods) or ‘nta’ (157 neighborhoods)
- Major NTA codes defined at
src/NeighborhoodLabels.ts:30-37
- Loaded from
display: none and are selectively shown by updateTier().
See implementation at src/NeighborhoodLabels.ts:94-112.
makeEl
<span> element with the appropriate CSS class:
- Base class:
nta-label - Tier-specific class:
nta-label--borough,nta-label--major, ornta-label--nta
src/NeighborhoodLabels.ts:114-119.
toVp
- Calls
latlngToImagePx(lat, lng)to get image pixel coordinates - Divides by
IMAGE_DIMS.widthto normalize to viewport coordinates (0-1 range)
src/NeighborhoodLabels.ts:86-92.
updateTier
src/NeighborhoodLabels.ts:121-140):
- Tier 0: Boroughs
- Tier 1: Major Neighborhoods
- Tier 2: All NTAs
Zoom < 1.5Shows only 5 borough labels (MANHATTAN, BROOKLYN, QUEENS, BRONX, STATEN ISLAND).
- Gets current zoom level from
viewer.viewport.getZoom() - Determines tier (0, 1, or 2) based on zoom thresholds
- Compares to
currentTier— returns early if unchanged (optimization) - Iterates through all labels and sets
displaystyle:- Tier 0: show only
tier === 'borough' - Tier 1: show
tier === 'borough'ortier === 'major' - Tier 2: show all labels
- Tier 0: show only
- Calls
draw()to reposition visible labels
draw
- Checks if labels are enabled (returns early if
!this.enabled) - Gets the current viewport from the viewer
- Iterates through all labels:
- Skips labels with
display: none - Converts viewport coordinates to screen pixels using
viewport.pixelFromPoint() - Sets
leftandtopstyles to position the label
- Skips labels with
update-viewport, zoom, and pan event to keep labels synchronized with the map.
See implementation at src/NeighborhoodLabels.ts:142-154.
Internal Data Structures
LabelEntry
Private Properties
Reference to the OpenSeadragon viewer instance
Absolutely-positioned container div for all label elements
Array of all label entries (boroughs + NTAs)
Current visibility tier (-1 = not initialized, 0 = boroughs, 1 = major, 2 = all)
Whether labels are currently enabled (default:
true)RequestAnimationFrame ID (reserved for future use, currently unused)
Usage Example
CSS Styling
The component expects the following CSS classes to be defined:Performance Considerations
- Manual positioning: Avoids OSD’s overlay system which calls
drawHTML()every frame and fights for element control - Tier change detection: Uses
currentTiertracking to avoid redundant show/hide operations - Display toggle optimization: Sets
display: noneinstead of removing elements from DOM - Pre-built labels: Creates all 202 label elements once during initialization, then toggles visibility
- Viewport caching: Stores viewport coordinates (
vpX,vpY) to avoid repeated lat/lng conversions
Data Sources
- Borough centroids: Hardcoded in
src/NeighborhoodLabels.ts:22-28 - NTA centroids: Loaded from
src/nta_centroids.json(197 neighborhoods) - Major NTA codes: Defined in
MAJOR_NTA_CODESSet (40 neighborhoods)
See Also
- App Component - Main React component that uses NeighborhoodLabels
- Coordinate Utilities -
latlngToImagePx()coordinate conversion