Overlay Components

Overlay components display HTML content positioned on the map at specific coordinates. Currently implemented components include tooltips and tooltip managers.

Overlay.Tooltip

Displays tooltips anchored to map coordinates with HTML content.

Basic Usage

<script>
	import { View, Map, Layer, Feature, Overlay, Interaction } from 'svelte-openlayers';
	import type { Feature as OlFeature } from 'ol';
	import type { Coordinate } from 'ol/coordinate';

	let hoverPosition: Coordinate | undefined = $state();
	let showTooltip = $state(false);
	let tooltipContent = $state('');

	function handleFeatureHover(feature: OlFeature | null, coordinate?: Coordinate) {
		if (!feature) {
			showTooltip = false;
			return;
		}

		tooltipContent = feature.get('name') || 'No name';
		hoverPosition = coordinate;
		showTooltip = true;
	}

	function hideTooltip() {
		showTooltip = false;
	}
</script>

<View center={[0, 0]} zoom={2}>
	<Map class="h-96 w-full">
		<Layer.Tile source="osm" />

		<Layer.Vector>
			<Feature.Point coordinates={[-74.0, 40.7]} properties={{ name: 'New York' }} />
			<Feature.Point coordinates={[-118.2, 34.0]} properties={{ name: 'Los Angeles' }} />
		</Layer.Vector>

		<Interaction.Hover onHover={handleFeatureHover} onHoverEnd={hideTooltip} />

		{#if showTooltip}
			<Overlay.Tooltip position={hoverPosition}>
				{tooltipContent}
			</Overlay.Tooltip>
		{/if}
	</Map>
</View>

Props

PropTypeDefaultDescription
position[number, number][0, 0]Tooltip anchor coordinates
contentstringundefinedTooltip text content
visiblebooleantrueTooltip visibility
offset[number, number][0, 0]Offset in pixels
positioning'bottom-left' | 'bottom-center' | 'bottom-right' | 'center-left' | 'center-center' | 'center-right' | 'top-left' | 'top-center' | 'top-right''bottom-center'Tooltip positioning relative to anchor
classstringundefinedCSS class for tooltip container
autoPanbooleanfalseAuto-pan map to show tooltip
overlayOverlay | nullnullBindable overlay instance (read-only)
childrenSnippetundefinedChild content (alternative to content prop)

Overlay.Hover

An overlay component designed to be used as a child of Feature components. It automatically appears when the parent feature is hovered and positions itself at the hover coordinate.

Basic Usage

<script>
	import { View, Map, Layer, Feature, Overlay } from 'svelte-openlayers';

	const cities = [
		{ name: 'New York', coords: [-74.0, 40.7] },
		{ name: 'Los Angeles', coords: [-118.2, 34.0] }
	];
</script>

<View center={[0, 0]} zoom={2}>
	<Map class="h-96 w-full">
		<Layer.Tile source="osm" />
		<Layer.Vector>
			{#each cities as city}
				<Feature.Point coordinates={city.coords} properties={city}>
					<Overlay.Hover>
						<div class="rounded bg-black px-2 py-1 text-xs text-white shadow">
							{city.name}
						</div>
					</Overlay.Hover>
				</Feature.Point>
			{/each}
		</Layer.Vector>
	</Map>
</View>

Props

PropTypeDefaultDescription
offset[number, number][0, -10]Offset from hover coordinate
positioning'bottom-left' | 'bottom-center' | 'bottom-right' | 'center-left' | 'center-center' | 'center-right' | 'top-left' | 'top-center' | 'top-right''bottom-center'Positioning relative to hover coordinate
classstringundefinedCSS class for overlay container
autoPanbooleanfalseAuto-pan map to show overlay
childrenSnippetundefinedContent to display in the overlay

Note: Overlay.Hover must be placed inside a Feature component with hover event handling enabled.

Overlay.Popup

An overlay component designed to be used as a child of Feature components. It automatically appears when the parent feature is selected and positions itself at the click coordinate.

Basic Usage

<script>
	import { View, Map, Layer, Feature, Overlay } from 'svelte-openlayers';

	const cities = [
		{ name: 'New York', coords: [-74.0, 40.7], population: '8M' },
		{ name: 'Los Angeles', coords: [-118.2, 34.0], population: '4M' }
	];
</script>

<View center={[0, 0]} zoom={2}>
	<Map class="h-96 w-full">
		<Layer.Tile source="osm" />
		<Layer.Vector>
			{#each cities as city}
				<Feature.Point coordinates={city.coords} properties={city}>
					<Overlay.Popup>
						<div class="rounded-lg bg-white p-3 shadow-lg">
							<div class="font-semibold">{city.name}</div>
							<div class="text-sm text-gray-600">Population: {city.population}</div>
						</div>
					</Overlay.Popup>
				</Feature.Point>
			{/each}
		</Layer.Vector>
	</Map>
</View>

Props

PropTypeDefaultDescription
offset[number, number][0, -15]Offset from click coordinate
positioning'bottom-left' | 'bottom-center' | 'bottom-right' | 'center-left' | 'center-center' | 'center-right' | 'top-left' | 'top-center' | 'top-right''bottom-center'Positioning relative to click coordinate
classstringundefinedCSS class for overlay container
autoPanbooleantrueAuto-pan map to show overlay
childrenSnippetundefinedContent to display in the overlay

Note: Overlay.Popup must be placed inside a Feature component with selection event handling enabled.

Overlay.Marker

An overlay component that renders custom HTML content as a marker at a feature’s position. Unlike Overlay.Hover and Overlay.Popup, markers are always visible and provide a way to display custom HTML/CSS as the visual representation of a feature.

Basic Usage

<script>
	import { View, Map, Layer, Feature, Overlay } from 'svelte-openlayers';

	const locations = [
		{ name: 'New York', coords: [-74.0, 40.7], color: '#ef4444' },
		{ name: 'Los Angeles', coords: [-118.2, 34.0], color: '#3b82f6' }
	];
</script>

<View center={[-96, 38]} zoom={4}>
	<Map class="h-96 w-full">
		<Layer.Tile source="osm" />
		<Layer.Vector>
			{#each locations as location}
				<Feature.Point coordinates={location.coords} properties={location}>
					<Overlay.Marker>
						<div class="marker" style="background-color: {location.color}">
							{location.name}
						</div>
					</Overlay.Marker>
				</Feature.Point>
			{/each}
		</Layer.Vector>
	</Map>
</View>

<style>
	.marker {
		padding: 4px 8px;
		border-radius: 4px;
		color: white;
		font-size: 12px;
		white-space: nowrap;
	}
</style>

Props

PropTypeDefaultDescription
offset[number, number][0, 0]Offset from feature coordinate in pixels
positioning'bottom-left' | 'bottom-center' | 'bottom-right' | 'center-left' | 'center-center' | 'center-right' | 'top-left' | 'top-center' | 'top-right''center-center'How the overlay is positioned relative to coord
classstringundefinedAdditional CSS classes for the marker container
autoPanbooleanfalseAuto-pan map to show marker when added
stopEventbooleantrueWhether to stop event propagation
overlayOverlay | nullnullBindable OpenLayers Overlay instance (read-only)
childrenSnippetundefinedHTML content for the marker

Note: Overlay.Marker must be placed inside a Feature component (Feature.Point, Feature.LineString, or Feature.Polygon).

Performance Considerations

Overlay.Marker creates a DOM element for each marker, which has performance implications:

  • Best for small datasets: Ideal when you have a limited number of features
  • DOM overhead: Each marker adds a DOM element that must be managed by the browser and repositioned during map interactions

When to use Overlay.Marker:

  • Rich HTML content (custom fonts, images, SVG icons, text labels)
  • Interactive elements (buttons, links)
  • CSS animations (pulsing indicators, transitions)
  • Small number of features

Combining Hover and Popup

You can use both hover and popup overlays on the same feature:

<Feature.Point coordinates={[-74.0, 40.7]} properties={{ name: 'New York', population: '8M' }}>
	<!-- Shows on hover -->
	<Overlay.Hover>
		<div class="rounded bg-gray-800 px-2 py-1 text-xs text-white">New York</div>
	</Overlay.Hover>

	<!-- Shows when selected -->
	<Overlay.Popup>
		<div class="rounded-lg bg-white p-4 shadow-xl">
			<h3 class="font-bold">New York</h3>
			<p>Population: 8M</p>
		</div>
	</Overlay.Popup>
</Feature.Point>

Overlay.TooltipManager

A higher-level component that automatically manages tooltips for hover and select interactions.

Basic Usage

<script>
	import { View, Map, Layer, Feature, Overlay } from 'svelte-openlayers';

	const cities = [
		{ name: 'New York', coords: [-74.0, 40.7], population: 8000000 },
		{ name: 'Los Angeles', coords: [-118.2, 34.0], population: 4000000 }
	];

	const selectedStyle = createCircleStyle({
		radius: 10,
		fill: { color: '#ef4444' },
		stroke: { color: '#991b1b', width: 3 }
	});
</script>

<View center={[-96, 38]} zoom={4}>
	<Map class="h-96 w-full">
		<Layer.Tile source="osm" />

		<Layer.Vector>
			{#each cities as city}
				<Feature.Point coordinates={city.coords} properties={city} />
			{/each}
		</Layer.Vector>

		<Overlay.TooltipManager selectStyle={selectedStyle} />
	</Map>
</View>

Props

PropTypeDefaultDescription
layersLayer[]undefinedLayers to show tooltips for
hitTolerancenumberundefinedHit detection tolerance
hoverTooltipbooleantrueEnable hover tooltips
selectTooltipbooleantrueEnable selection tooltips
hoverContent(feature: Feature) => stringundefinedFunction to generate hover tooltip content
selectContent(feature: Feature) => stringundefinedFunction to generate select tooltip content
hoverSnippetSnippet<[Feature]>undefinedSvelte snippet for hover tooltip content
selectSnippetSnippet<[Feature]>undefinedSvelte snippet for select tooltip content
hoverPositioningPositioning options (same as Overlay.Tooltip)'center-left'Hover tooltip positioning
selectPositioningPositioning options (same as Overlay.Tooltip)'center-left'Select tooltip positioning
hoverClassstring'hover-tooltip'CSS class for hover tooltips
selectClassstring'select-tooltip'CSS class for select tooltips
selectStyleStyleLikeundefinedStyle for selected features
selectInteractionInteractionnullBindable select interaction instance
hoverInteractionInteractionnullBindable hover interaction instance
selectedFeaturesReactiveCollection<Feature>nullBindable reactive selected features collection
multibooleanfalseAllow multiple selection
reactivebooleantrueEnable automatic reactivity (set to false for performance)

Performance Considerations

When building maps with interactive features, choosing the right overlay strategy is critical for performance.

Overlay.Hover and Overlay.Popup (Per-Feature Overlays)

These overlays are defined as children of Feature components. Each feature with an overlay creates a DOM element that OpenLayers manages.

Best for:

  • Small to medium datasets
  • Features with unique, complex popup content
  • Cases where each feature has different overlay behavior
<!-- Each city creates its own overlay instances -->
{#each cities as city}
	<Feature.Point coordinates={city.coords} properties={city}>
		<Overlay.Hover>
			<div>{city.name}</div>
		</Overlay.Hover>
		<Overlay.Popup>
			<CityDetails {city} />
		</Overlay.Popup>
	</Feature.Point>
{/each}

Overlay.TooltipManager (Map-Level Centralized Overlay)

The Overlay.TooltipManager uses a single overlay for each tooltip type (hover and select), dynamically updating content and position based on the current feature.

Best for:

  • Large datasets (hundreds to thousands of features)
  • Features with similar tooltip patterns
  • Maximum performance with minimal DOM overhead
<!-- Single Overlay.TooltipManager for all features -->
<Layer.Vector>
	{#each thousandsOfCities as city}
		<Feature.Point coordinates={city.coords} properties={city} />
	{/each}
</Layer.Vector>

<Overlay.TooltipManager
	hoverContent={(feature) => feature.get('name')}
	selectContent={(feature) => 'Population: ' + feature.get('population')}
/>

Combining approaches: You can use both - Overlay.TooltipManager for bulk features and Overlay.Popup for specific features that need unique behavior:

<Layer.Vector>
	{#each regularCities as city}
		<Feature.Point coordinates={city.coords} properties={city} />
	{/each}
	<!-- Special feature with unique popup -->
	<Feature.Point coordinates={specialCity.coords} properties={specialCity}>
		<Overlay.Popup>
			<SpecialCityWidget />
		</Overlay.Popup>
	</Feature.Point>
</Layer.Vector>
<Overlay.TooltipManager layers={[regularLayer]} />