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:

ComponentDescription
VLayerMaplibreGeojsonGeoJSON data visualization
VLayerMaplibreVectorVector tile layers
VLayerMaplibreRasterRaster tile layers
VLayerMaplibreImageGeoreferenced images
VLayerMaplibreVideoGeoreferenced video
VLayerMaplibreCanvasCustom canvas rendering
VLayerMaplibrePmtilePMTiles archives

Custom Layers

Higher-level components that compose multiple MapLibre layers:

VLayerMaplibreCluster

Clustered point visualization with automatic grouping.

Props

PropTypeDefaultDescription
sourceIdstring'cluster-source'GeoJSON source ID
baseLayerIdstring'cluster'Base ID for generated layers
sourceGeoJSONSourceSpecification-GeoJSON source configuration
visibilitybooleantrueLayer visibility
clusterPaintobjectSee belowCluster circle styling
unclusteredPaintobjectSee belowIndividual point styling
textPaintobjectSee belowCluster count text styling

Events

EventPayloadDescription
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

PropTypeDefaultDescription
idstringAuto-generatedUnique route identifier
coordinates[number, number][]-Array of lng, lat coordinates
colorstring'#4285F4'Line color
widthnumber4Line width in pixels
opacitynumber1Line opacity (0-1)
lineCap'butt' | 'round' | 'square''round'Line cap style
lineJoin'bevel' | 'round' | 'miter''round'Line join style
visiblebooleantrueRoute visibility
interactivebooleantrueEnable hover/click
dashArraynumber[]-Dash pattern for dashed lines
blurnumber0Line blur in pixels

Events

EventPayloadDescription
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.

Isochrones show areas reachable within a specific time or distance from a point. They're commonly used for delivery coverage, commute analysis, and accessibility mapping.

Props

PropTypeDefaultDescription
idstringAuto-generatedUnique layer identifier
dataIsochroneData | null-GeoJSON FeatureCollection from routing API
fillOpacitynumber0.4Polygon fill opacity (0-1)
lineWidthnumber2Outline width in pixels
lineOpacitynumber0.8Outline opacity (0-1)
visiblebooleantrueLayer visibility
interactivebooleantrueEnable hover/click
reverseOrderbooleantrueReverse feature order for proper stacking

Events

EventPayloadDescription
click{ feature, coordinates }Polygon clicked
mouseenterfeatureMouse 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