Layers
MapLibre Layers
Native MapLibre GL layers and custom derived layers
MapLibre Layers
Native MapLibre GL layer components for common use cases.
Base Layers
These components wrap MapLibre's native layer types:
| Component | Description |
|---|---|
VLayerMaplibreGeojson | GeoJSON data visualization |
VLayerMaplibreVector | Vector tile layers |
VLayerMaplibreRaster | Raster tile layers |
VLayerMaplibreImage | Georeferenced images |
VLayerMaplibreVideo | Georeferenced video |
VLayerMaplibreCanvas | Custom canvas rendering |
VLayerMaplibrePmtile | PMTiles archives |
Custom Layers
Higher-level components that compose multiple MapLibre layers:
VLayerMaplibreCluster
Clustered point visualization with automatic grouping.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
sourceId | string | 'cluster-source' | GeoJSON source ID |
baseLayerId | string | 'cluster' | Base ID for generated layers |
source | GeoJSONSourceSpecification | - | GeoJSON source configuration |
visibility | boolean | true | Layer visibility |
clusterPaint | object | See below | Cluster circle styling |
unclusteredPaint | object | See below | Individual point styling |
textPaint | object | See below | Cluster count text styling |
Events
| Event | Payload | Description |
|---|---|---|
cluster-click | { features, coordinates } | Cluster circle clicked |
point-click | { features, coordinates } | Individual point clicked |
Example
<script setup lang="ts">
import { VMap, VLayerMaplibreCluster } from '@geoql/v-maplibre';
const earthquakes = ref({
type: 'FeatureCollection',
features: [], // Load your point data
});
</script>
<template>
<VMap :options="mapOptions">
<VLayerMaplibreCluster
source-id="earthquakes"
base-layer-id="quakes"
:source="{ type: 'geojson', data: earthquakes }"
@cluster-click="handleClusterClick"
@point-click="handlePointClick"
/>
</VMap>
</template>
VLayerMaplibreRoute
Route/path visualization for navigation and delivery tracking.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | Auto-generated | Unique route identifier |
coordinates | [number, number][] | - | Array of lng, lat coordinates |
color | string | '#4285F4' | Line color |
width | number | 4 | Line width in pixels |
opacity | number | 1 | Line opacity (0-1) |
lineCap | 'butt' | 'round' | 'square' | 'round' | Line cap style |
lineJoin | 'bevel' | 'round' | 'miter' | 'round' | Line join style |
visible | boolean | true | Route visibility |
interactive | boolean | true | Enable hover/click |
dashArray | number[] | - | Dash pattern for dashed lines |
blur | number | 0 | Line blur in pixels |
Events
| Event | Payload | Description |
|---|---|---|
click | { coordinates } | Route line clicked |
mouseenter | - | Mouse enters route |
mouseleave | - | Mouse leaves route |
Example
<script setup lang="ts">
import { VMap, VLayerMaplibreRoute } from '@geoql/v-maplibre';
const routeCoordinates = ref([
[-122.4194, 37.7749],
[-122.4089, 37.7855],
[-122.3984, 37.7925],
]);
</script>
<template>
<VMap :options="mapOptions">
<VLayerMaplibreRoute
id="my-route"
:coordinates="routeCoordinates"
color="#10b981"
:width="5"
@click="handleRouteClick"
/>
</VMap>
</template>
VLayerMaplibreIsochrone
Isochrone/isodistance polygon visualization for travel time analysis.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | Auto-generated | Unique layer identifier |
data | IsochroneData | null | - | GeoJSON FeatureCollection from routing API |
fillOpacity | number | 0.4 | Polygon fill opacity (0-1) |
lineWidth | number | 2 | Outline width in pixels |
lineOpacity | number | 0.8 | Outline opacity (0-1) |
visible | boolean | true | Layer visibility |
interactive | boolean | true | Enable hover/click |
reverseOrder | boolean | true | Reverse feature order for proper stacking |
Events
| Event | Payload | Description |
|---|---|---|
click | { feature, coordinates } | Polygon clicked |
mouseenter | feature | Mouse enters polygon |
mouseleave | - | Mouse leaves polygon |
Data Format
The component accepts GeoJSON from routing APIs like Valhalla or OSRM. It automatically handles color format conversion (Valhalla returns colors without # prefix).
interface IsochroneData {
type: 'FeatureCollection';
features: Array<{
type: 'Feature';
properties: {
color: string; // e.g., '2563eb' or '#2563eb'
contour?: number; // Time in minutes or distance
metric?: string; // 'time' or 'distance'
};
geometry: Polygon | MultiPolygon;
}>;
}
Example with Valhalla API
<script setup lang="ts">
import { VMap, VMarker, VLayerMaplibreIsochrone } from '@geoql/v-maplibre';
const originPoint = ref<[number, number]>([-73.985, 40.758]);
const isochroneData = ref(null);
async function fetchIsochrone() {
const params = {
locations: [{ lat: originPoint.value[1], lon: originPoint.value[0] }],
costing: 'auto',
contours: [
{ time: 5, color: '2563eb' },
{ time: 10, color: '7c3aed' },
{ time: 15, color: 'db2777' },
],
polygons: true,
};
const response = await fetch(`/api/isochrone?json=${encodeURIComponent(JSON.stringify(params))}`);
isochroneData.value = await response.json();
}
function handleMarkerDrag(event) {
const lngLat = event.target.getLngLat();
originPoint.value = [lngLat.lng, lngLat.lat];
fetchIsochrone();
}
</script>
<template>
<VMap :options="mapOptions" @loaded="fetchIsochrone">
<VLayerMaplibreIsochrone
id="travel-zones"
:data="isochroneData"
:fill-opacity="0.5"
@click="handleZoneClick"
/>
<VMarker
:coordinates="originPoint"
:options="{ draggable: true }"
@dragend="handleMarkerDrag"
/>
</VMap>
</template>
Use Cases
- Real Estate: Show commute times to office locations
- Logistics: Determine delivery coverage areas
- Urban Planning: Analyze accessibility of public services
- Emergency Services: Visualize response time coverage