Install svelte-maplibre via npm
masterTo add svelte-maplibre to your project, use the following npm command:
npm install svelte-maplibrerepository·master·Indexed 19 days ago
https://github.com/dimfeld/svelte-maplibreSvelte bindings for the MapLibre GL JS mapping library, providing a wrapper to integrate MapLibre into Svelte applications. It includes a MapLibre component, specialized layer components (such as FillLayer, SymbolLayer, and HeatmapLayer), source components (GeoJSON, VectorTileSource, etc.), and map controls. The library also provides utilities for managing map context, generating viewport hashes, and creating MapLibre expressions and filters.
To add svelte-maplibre to your project, use the following npm command:
npm install svelte-maplibreThe library uses Svelte's context API combined with a Box<T> wrapper to provide reactive state to deeply nested components.
Box<T>: A wrapper around a $state() value. When you retrieve a Box from a context (like getLayer()), you access or update its value via the .value property.setLayer, setSource, setCluster) to communicate with their parents. This allows for a declarative structure where a layer component automatically knows which source it should be associated with by looking up the context tree.// Conceptual usage of the Box pattern
import { getLayer } from 'svelte-maplibre';
const layerBox = getLayer();
if (layerBox) {
// Accessing the reactive value
console.log(layerBox.value);
// Updating the reactive value
layerBox.value = 'new-layer-id';
}To use ESLint with Svelte in this project, call createConfig(true). This enables the following:
eslint-plugin-svelte recommended rules (flat/recommended).flat/prettier).**/*.svelte files using the TypeScript parser.svelte/valid-compile to prevent duplicate warnings in editors.Note: The configuration automatically includes globals.browser and globals.node.
import { createConfig } from './eslint.config.js';
export default createConfig(true);To render a map, import the MapLibre component from svelte-maplibre. You can configure the map's center, zoom level, and style URL via props. Note that you must provide a height for the map container via CSS (using :global if the class is applied to the component).
<script>
import { MapLibre } from 'svelte-maplibre';
</script>
<MapLibre
center={[50,20]}
zoom={7}
class="map"
standardControls
style="https://basemaps.cartocdn.com/gl/positron-gl-style/style.json" />
<style>
:global(.map) {
height: 500px;
}
</style>The removeSource function safely removes a source from the map. It uses Svelte's tick() to wait for any associated layers to have a chance to remove themselves before attempting to remove the source. To prevent accidental removal of a newly added source that might have reused the same ID, it verifies that the source currently on the map is the exact same object (sourceObj) that was intended for removal.
Parameters:
map: The MapLibre Map instance.sourceId: The ID of the source to remove.sourceObj: The original source object that was added, used for identity verification before removal.import { removeSource } from './path-to-source';
// Assuming 'originalSource' is the object returned or stored from the addition
removeSource(mapInstance, 'my-source-id', originalSource);The boundsEqual utility compares a provided LngLatBoundsLike parameter against the current map bounds, accounting for floating-point precision.
export function boundsEqual(
param: LngLatBoundsLike,
mapBounds: MapLibre.LngLatBounds | undefined
): { equal: boolean; bounds: MapLibre.LngLatBounds }Use getViewportHash(map) to generate a string representation of the current MapLibre GL map state (zoom, center, bearing, and pitch). This hash can be used to store or share a specific map view via a URL fragment. The resulting string starts with a # and follows the format #zoom/lat/lng[/bearing][/pitch].
import type { Map } from 'maplibre-gl';
import { getViewportHash } from 'svelte-maplibre';
// Assuming 'map' is an instance of MapLibre GL Map
const hash = getViewportHash(map);
console.log(hash); // e.g., "#12/52.52/13.40/0/45"You can restrict the zoom range for specific components or groups of components using setZoomLimits(min, max). This creates a ZoomRange context that layers can inherit. If a layer has its own zoom settings, they will override the parent's settings, but will still be constrained by the parent's bounds.
import { setZoomLimits, getZoomLimits } from 'svelte-maplibre';
// Set limits for a specific section of your map
setZoomLimits(5, 15);
// Retrieve current limits
const limits = getZoomLimits();
// limits.minzoom and limits.maxzoomThe addSource function adds a MapLibre source to a map instance. It includes logic to handle race conditions where a source with the same ID might be in the process of being removed, ensuring the new source is added only after the old one is gone.
Parameters:
map: The MapLibre Map instance.sourceId: A unique string ID for the source.source: A SourceSpecification object defining the source data.okToAdd: A callback function (sourceId: string) => boolean used to verify if the source should still be added (e.g., checking if the component is still mounted or the ID hasn't changed).cb: A callback function () => void executed once the source has been successfully added.import type { Map, SourceSpecification } from 'maplibre-gl';
import { addSource } from './path-to-source';
addSource(
mapInstance,
'my-source-id',
{ type: 'geojson', data: myGeojsonData },
(id) => id === 'my-source-id', // okToAdd check
() => console.log('Source added!') // cb
);The zoomTransition function creates a MapLibre interpolate expression that changes a value based on the map's current zoom level using a ['linear'] interpolation method. This is commonly used for scaling icon sizes, opacity, or line widths as the user zooms in or out.
import { zoomTransition } from 'svelte-maplibre/expressions';
// Example: Scale icon size from 10 to 30 between zoom levels 5 and 15
const iconSize = zoomTransition(5, 10, 15, 30);
const layer = {
type: 'symbol',
layout: {
'icon-size': iconSize
}
};The isTextLayer utility checks if a given maplibregl.LayerSpecification is a symbol layer that contains a text-field layout property. You can optionally restrict the check to a specific source name.
import { isTextLayer } from 'svelte-maplibre/filters';
const layer = {
type: 'symbol',
source: 'my-source',
layout: { 'text-field': '{name}' }
};
const isText = isTextLayer(layer, 'my-source'); // true
const isWrongSource = isTextLayer(layer, 'other-source'); // falseThe convertBoundsToUserFormat function converts MapLibre.LngLatBounds into a user-friendly LngLatBoundsLike format (such as a flat array of 4 numbers or nested arrays), depending on the provided param structure.
export function convertBoundsToUserFormat(
bounds: MapLibre.LngLatBounds,
param: LngLatBoundsLike | undefined
): LngLatBoundsLike