Examples
Explore practical, production-ready examples of vue3-maplibre-gl v5 components and composables in action.
Quick Start
Installation
bun add vue3-maplibre-gl
# or
npm install vue3-maplibre-glImport CSS
// main.ts or in your component
import 'vue3-maplibre-gl/dist/style.css';Basic Usage
<template>
<Maplibre :options="mapOptions" style="height: 500px">
<GeoJsonSource :data="geoData">
<CircleLayer :style="circleStyle" />
</GeoJsonSource>
</Maplibre>
</template>
<script setup>
import { ref } from 'vue';
import { Maplibre, GeoJsonSource, CircleLayer } from 'vue3-maplibre-gl';
import 'vue3-maplibre-gl/dist/style.css';
const mapOptions = ref({
style: 'https://demotiles.maplibre.org/style.json',
center: [0, 0],
zoom: 2,
});
const geoData = ref({
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: { type: 'Point', coordinates: [0, 0] },
properties: { name: 'Center' },
},
],
});
const circleStyle = ref({
'circle-radius': 6,
'circle-color': '#007cbf',
});
</script>Available Examples
🗺️ Basic Map
Create a simple interactive map with style switching and configuration options.
Topics Covered:
- Map initialization with options
- Style switching (OSM, satellite, etc.)
- Reactive property updates
- Event handling (load, click, zoom)
- Camera controls and state
Key Composables:
useCreateMaplibre()- Map creationuseMaplibre()- Map context accessuseFlyTo()- Smooth camera animation
📍 Markers
Add interactive markers to your map with advanced features.
Topics Covered:
- Marker creation and positioning
- Draggable markers with event handling
- Marker popups with custom content
- Marker clustering
- Marker icons and styling
- Marker removal and updates
Key Composables:
useCreateMarker()- Programmatic marker creationuseCreatePopup()- Marker popupsuseMapEventListener()- Interaction events
Key Components:
<Marker />- Marker component<PopUp />- Popup overlays
🎨 Layers
Work with all layer types: Fill, Circle, Line, and Symbol layers.
Topics Covered:
- Fill layers for polygons with styling
- Circle layers for points with size/color
- Line layers for routes/boundaries
- Symbol layers for text/icons
- Layer painting and layout properties
- Reactive style updates
- Layer filtering by properties
- Layer z-order management
Key Composables (all with full type safety):
useCreateFillLayer()- Fill layersuseCreateCircleLayer()- Circle layersuseCreateLineLayer()- Line layersuseCreateSymbolLayer()- Symbol layers
Key Components:
<FillLayer />- Fill layer component<CircleLayer />- Circle layer component<LineLayer />- Line layer component<SymbolLayer />- Symbol layer component
🎮 Controls
Integrate navigation controls and geolocation features.
Topics Covered:
- Geolocation control initialization
- User location tracking
- Geolocation events and permissions
- Custom control positioning
- Control state management
- Error handling for location services
Key Composables:
useGeolocateControl()- Programmatic geolocationuseGeolocateEventListener()- Geolocate events
Key Components:
<GeolocateControls />- Geolocation control
Example Structure
Each example includes:
| Section | Content |
|---|---|
| Live Demo | Interactive map with full functionality |
| Code | Complete Vue component with explanations |
| Features | Key capabilities highlighted |
| APIs | Links to relevant composables/components |
| Variations | Alternative approaches and patterns |
Common Patterns
Data Updates
const geoData = ref({ type: 'FeatureCollection', features: [] });
// Update data reactively
watch(
() => selectedRegion.value,
(region) => {
const filtered = allFeatures.filter((f) => f.properties.region === region);
geoData.value = { type: 'FeatureCollection', features: filtered };
},
);Camera Animations
const { flyTo } = useFlyTo(mapInstance);
const animateToLocation = async (location) => {
try {
await flyTo({ center: location, zoom: 10 });
} catch (error) {
console.error('Animation failed:', error);
}
};Event Handling
const { isListenerAttached } = useMapEventListener('click', (e) => {
console.log('Clicked at:', e.lngLat);
// Get features at click point
const features = mapInstance.value?.queryRenderedFeatures({
layers: ['my-layer'],
});
});Layer Styling
const { setPaint, setFilter } = useCreateCircleLayer(mapInstance, sourceId);
// Type-safe property updates
watch(
() => settings.radius,
(newRadius) => {
setPaint({ 'circle-radius': newRadius, 'circle-color': '#088' });
},
);
watch(
() => filters.name,
(name) => {
setFilter(['in', 'name', ...name.split(',')]);
},
);Running Examples Locally
Using the Example App
Clone the repository and run the example app:
git clone https://github.com/danh121097/vue-maplibre-gl
cd vue-maplibre-gl/examples
bun install
bun devThen open the local URL shown in your terminal (usually localhost on port 5173).
Copy & Paste
You can copy any example code and paste it into your Vue 3 project. All examples are standalone and include necessary imports.
Best Practices
Always handle map readiness before operations
typescriptwatch(isMapReady, () => { // Map is interactive now });Use type-safe layer composables for compile-time validation
typescriptconst { setPaint } = useCreateFillLayer(map, source); // setPaint only accepts FillPaint typesAwait camera animations for sequential operations
typescriptawait flyTo({ center: [0, 0], zoom: 10 }); // Camera animation completeClean up listeners (automatic with composables)
typescriptconst { removeListener } = useMapEventListener('click', handler); // Removed on component unmount automaticallyUse reactive data for real-time updates
typescriptconst geoData = ref({...}); watch(() => externalData, () => { geoData.value = transformedData; });
Advanced Topics
Performance Optimization
- Use
GeoJsonSourcewith clustering for large datasets - Filter data on the backend before sending
- Use
watchwith debounce for frequent updates - Optimize GeoJSON complexity (simplify geometries)
State Management
- Use
registercallback for Pinia/Vuex integration - Store map state in application state management
- Sync URL params with map camera position
Custom Controls
- Build on top of
useMaplibre()composable - Listen to map events with
useMapEventListener() - Update UI based on map state reactively
Troubleshooting
Map Not Showing
- Check: Container has height (e.g.,
style="height: 500px") - Check: CSS is imported (
import 'vue3-maplibre-gl/dist/style.css') - Check: MapOptions includes valid
styleURL
Events Not Firing
- Check: Listener attached before map ready
- Check: Event name is correct (see MapLibre GL docs)
- Check: Map instance is valid and ready
Data Not Updating
- Check: Using
ref()for reactive data - Check: Updating
geoData.valuenot reassigning - Check: Source ID matches layer sourceId
More Resources
- Component API Reference
- Composables API Reference
- Type Reference
- Getting Started Guide
- SSR/Nuxt Guide
- GitHub Repository
- Install dependencies:
yarn install - Start the development server:
yarn dev - Navigate to the examples section
Contributing Examples
Have a great example to share? We welcome contributions! Please:
- Fork the repository
- Create a new example file in the appropriate category
- Follow the existing example format
- Submit a pull request
Need Help?
- Check the API documentation for component details
- Review composables documentation for advanced functionality
- Visit our GitHub repository for issues and discussions