wakeb-map

A free Vue 3 multi-provider map library (Leaflet + Mapbox GL JS + extensible) with location picking, markers, geocoding, drawing, tracking, and more. No API key required for Leaflet. Works offline!
2,716
Install
npm install wakeb-map
Latest Version:2.3.0
Vue:3
License:MIT
Last Updated:May 5, 2026
Links: npm
Maintainer: keroloszakaria

wakeb-map

A free, multi-provider Vue 3 map library supporting Leaflet, Mapbox GL JS, Google Maps, and custom providers.
Default engine: Leaflet + OpenStreetMap — zero API key needed.
Includes a built-in SVG vector map engine (world maps, regions, markers, lines — no external dependencies).
Full offline support, 19 composables, 3 components, and 30+ utility functions.

npm license


Features

Components

Component Description
<WakebMap> Multi-provider map — markers, polylines, circles, polygons, drawing, fullscreen, layer switching
<WakebMapPicker> Ready-made location picker — search, pin, confirm, address display
<WakebVectorMap> Pure SVG vector map — world regions, data visualization, series, tooltips (zero deps)

Composables (19)

Category Composables
Core useWakebMap · useDrawing · useGeofence · useMarkerCluster · useWakebTracking
Fleet useFleetTracking · useRouteFollowing
Visualization useChoropleth · useHeatmap · useTimeSlider
Routing useRouting · useGeocoder · useElevation
Overlays useImageOverlay · useWMS · useLiveData
UI useMapScreenshot · useMinimap
Vector useVectorMap

Key Highlights

  • 100% Free — no API key, no subscription, no usage limits (Leaflet default)
  • Multi-Provider — switch between Leaflet, Mapbox GL JS, or Google Maps per-component with one prop
  • Works Offline — built-in canvas tile layer, inline SVG markers, Haversine distance — all work without internet
  • Vector Map Engine — pure SVG renderer with regions, markers, curved/straight lines, animated dash flow, fade-in animations, data series, tooltips, zoom/pan, touch support
  • 5 Map Styles — streets, satellite, topo, dark, offline (auto-mapped across providers)
  • Free Geocoding — Nominatim address search + reverse geocode
  • Drawing — paths, polygons, rectangles, circles, measurements, with constraint boundaries
  • Fleet Tracking — real-time vehicle/entity tracking with animated movement
  • Full TypeScript — every type exported

Installation

npm install wakeb-map

vue (>=3.3) and leaflet (>=1.9.4) are peer dependencies:

npm install wakeb-map leaflet
npm install -D @types/leaflet

Optional: Mapbox GL JS

npm install mapbox-gl

Then register the provider:

import mapboxgl from "mapbox-gl";
import "mapbox-gl/dist/mapbox-gl.css";
import { createMapboxProvider, registerProvider } from "wakeb-map";

registerProvider(createMapboxProvider(mapboxgl));

Optional: Google Maps

npm install @googlemaps/js-api-loader

Then register the provider:

import { Loader } from "@googlemaps/js-api-loader";
import { createGoogleMapsProvider, registerProvider } from "wakeb-map";

const google = await new Loader({ apiKey: "YOUR_KEY" }).load();
registerProvider(createGoogleMapsProvider(google));

Quick Start

Basic Map

<template>
  <WakebMap
    :center="{ lat: 24.7136, lng: 46.6753 }"
    :zoom="14"
    :markers="markers"
    height="500px"
    @click="onMapClick"
    @marker-click="onMarkerClick"
  />
</template>

<script setup lang="ts">
import { ref } from "vue";
import { WakebMap } from "wakeb-map";
import "wakeb-map/style.css";
import type { WakebLatLng, WakebMarker } from "wakeb-map";

const markers = ref<WakebMarker[]>([
  {
    id: "1",
    position: { lat: 24.7136, lng: 46.6753 },
    title: "Riyadh",
    snippet: "Capital of Saudi Arabia",
  },
]);

function onMapClick(e: { position: WakebLatLng }) {
  console.log("Clicked:", e.position.lat, e.position.lng);
}

function onMarkerClick(marker: WakebMarker) {
  console.log("Marker:", marker.title);
}
</script>

Location Picker

<template>
  <WakebMapPicker
    v-model="location"
    height="500px"
    confirm-label="Confirm Location"
    @location-picked="onPicked"
  />
</template>

<script setup lang="ts">
import { ref } from "vue";
import { WakebMapPicker } from "wakeb-map";
import "wakeb-map/style.css";
import type { WakebLatLng } from "wakeb-map";

const location = ref<WakebLatLng | null>(null);

function onPicked(result: { position: WakebLatLng; address: string }) {
  console.log(result.position, result.address);
}
</script>

Vector Map (SVG — No External Dependencies)

<template>
  <div ref="mapEl" style="width: 100%; height: 400px" />
</template>

<script setup lang="ts">
import { ref, onMounted } from "vue";
import { useVectorMap } from "wakeb-map";

const mapEl = ref<HTMLElement | null>(null);

const vectorMap = useVectorMap({
  map: "world",
  regionStyle: {
    initial: { fill: "#d1d5db", stroke: "#fff", strokeWidth: 0.5 },
    hover: { fill: "#3b82f6", fillOpacity: 0.8 },
    selected: { fill: "#10b981" },
  },
  markerStyle: {
    initial: { fill: "#ef4444", stroke: "#fff", r: 6 },
    hover: { fill: "#f59e0b", r: 8 },
  },
  lineStyle: {
    stroke: "#3b82f6",
    strokeWidth: 1.5,
    strokeDasharray: "6 3 6",
    animation: true,
    curvature: 0.15,
  },
  zoomButtons: true,
  showTooltip: true,
  regionsSelectable: true,
});

onMounted(() => {
  if (mapEl.value) vectorMap.init(mapEl.value);

  vectorMap.addMarkers([
    { name: "Cairo", coords: [30.04, 31.24] },
    { name: "London", coords: [51.51, -0.13] },
    { name: "Tokyo", coords: [35.68, 139.69] },
  ]);

  vectorMap.addLines([
    { from: "Cairo", to: "London" },
    { from: "London", to: "Tokyo" },
  ]);
});
</script>

Plugin Setup (Optional)

Register globally to set default center, zoom, map type, provider, and offline options:

import { createApp } from "vue";
import { WakebMapPlugin } from "wakeb-map";
import "wakeb-map/style.css";

const app = createApp(App);

app.use(WakebMapPlugin, {
  language: "ar",
  defaultCenter: { lat: 24.7136, lng: 46.6753 },
  defaultZoom: 14,
  defaultMapType: "streets",
  // provider: "mapbox",          // uncomment to use Mapbox as default
  // mapboxAccessToken: "pk.xxx", // required when using Mapbox
  // provider: "google",          // uncomment to use Google Maps as default
});

app.mount("#app");

Offline Mode

Full offline support — the map, markers, shapes, GPS, and distance all work without internet.

// Option 1: Plugin config
app.use(WakebMapPlugin, {
  offline: true,
  offlineGridColor: "#ddd",
  offlineBgColor: "#f0f0f0",
});

// Option 2: Component prop
// <WakebMap map-type="offline" />

// Option 3: Manual tile layer
import { createOfflineTileLayer } from "wakeb-map";
const offlineLayer = createOfflineTileLayer({ offlineGridColor: "#ccc" });
Feature Offline?
Map rendering ✅ Canvas coordinate grid
Markers ✅ Inline SVG icons (no CDN)
Shapes ✅ Lines, circles, polygons
GPS ✅ Browser hardware
Distance ✅ Haversine formula (local)
Vector Map ✅ Pure SVG (fully embedded)
Address search ❌ Requires internet
Geocoding ❌ Returns null gracefully

Map Providers

Switching Providers

<!-- Default: Leaflet (no setup needed) -->
<WakebMap :center="center" :zoom="14" height="400px" />

<!-- Mapbox GL JS -->
<WakebMap
  provider="mapbox"
  access-token="pk.xxx"
  :center="center"
  :zoom="14"
  height="400px"
/>

<!-- Google Maps -->
<WakebMap provider="google" :center="center" :zoom="14" height="400px" />

<!-- All three on the same page -->
<WakebMap :center="center" :zoom="14" height="400px" />
<WakebMap
  provider="mapbox"
  access-token="pk.xxx"
  :center="center"
  :zoom="14"
  height="400px"
/>
<WakebMap provider="google" :center="center" :zoom="14" height="400px" />

Provider Comparison

Feature Leaflet Mapbox GL JS Google Maps
API Key Not needed Required (free tier) Required (free tier)
Tile Rendering Raster Vector (WebGL) Vector
3D Terrain No Yes Limited
Offline Support Yes (canvas tiles) No No
Bundle Size ~40 KB ~200 KB Loaded via script

Composable Compatibility

Composable Leaflet Mapbox Google Notes
useWakebMap ✅ ✅ ✅ Provider-independent (reactive)
useWakebTracking ✅ ✅ ✅ Provider-independent
useFleetTracking ✅ ✅ ✅ Provider-independent
useRouteFollowing ✅ ✅ ✅ Provider-independent
useGeofence ✅ ✅ ✅ Provider-independent
useMarkerCluster ✅ ✅ ✅ Provider-independent
useTimeSlider ✅ ✅ ✅ Provider-independent
useLiveData ✅ ✅ ✅ Provider-independent
useVectorMap ✅ ✅ ✅ Pure SVG, no map engine dependency
useDrawing ✅ ❌ ❌ Leaflet L.Draw only
useChoropleth ✅ ❌ ❌ Leaflet GeoJSON layers
useHeatmap ✅ ❌ ❌ Leaflet heatmap plugin
useElevation ✅ ❌ ❌ Leaflet elevation control
useGeocoder ✅ ❌ ❌ Leaflet geocoder control
useImageOverlay ✅ ❌ ❌ Leaflet image overlay
useMapScreenshot ✅ ❌ ❌ Leaflet canvas export
useMinimap ✅ ❌ ❌ Leaflet minimap control
useRouting ✅ ❌ ❌ Leaflet routing machine
useWMS ✅ ❌ ❌ Leaflet WMS layer

Map Styles

Style Source Online?
streets OpenStreetMap Yes
satellite Esri World Imagery Yes
topo OpenTopoMap Yes
dark CARTO Dark Yes
offline Built-in canvas No
<WakebMap map-type="satellite" />
<WakebMap map-type="dark" />
<WakebMap map-type="topo" />
<WakebMap map-type="offline" />

Composable Examples

useWakebMap

import { useWakebMap } from "wakeb-map";

const {
  position,
  address,
  zoom,
  markers,
  loading,
  setPosition,
  pickMyLocation,
  searchAddress,
  addMarker,
  distanceTo,
} = useWakebMap({ lat: 24.7136, lng: 46.6753 });

useDrawing

import { useDrawing } from "wakeb-map";

const drawing = useDrawing();
drawing.bindMap(leafletMap);
drawing.startDrawing("polygon", { color: "#2196F3", showMeasurements: true });
const result = drawing.finishDrawing();

useGeocoder

import { useGeocoder } from "wakeb-map";

const { search, reverse, results, loading } = useGeocoder();
await search("Kingdom Tower, Riyadh");
await reverse({ lat: 24.7136, lng: 46.6753 });

useRouting

import { useRouting } from "wakeb-map";

const { calculateRoute, route, instructions } = useRouting();
await calculateRoute(
  { lat: 24.7136, lng: 46.6753 },
  { lat: 21.4225, lng: 39.8262 },
  { profile: "driving" },
);

useHeatmap

import { useHeatmap } from "wakeb-map";

const { addPoints, setOptions } = useHeatmap(leafletMap);
addPoints([
  { lat: 24.71, lng: 46.67, intensity: 0.8 },
  { lat: 24.72, lng: 46.68, intensity: 0.5 },
]);

useFleetTracking

import { useFleetTracking } from "wakeb-map";

const fleet = useFleetTracking(leafletMap, {
  showTrails: true,
  animateMovement: true,
});
fleet.updateEntity({
  id: "truck-1",
  type: "truck",
  position: { lat: 24.7, lng: 46.6 },
});

Utilities

Geocoding (Free — Nominatim)

import { reverseGeocode, geocodeAddress } from "wakeb-map";

const addr = await reverseGeocode({ lat: 24.7136, lng: 46.6753 });
const pos = await geocodeAddress("Kingdom Tower, Riyadh");

Distance & Geometry

import {
  calculateDistance,
  calculateBearing,
  midpoint,
  isPointInPolygon,
  isPointInCircle,
  polygonArea,
  pathLength,
  getBoundingBox,
  convexHull,
  simplifyPath,
  bufferPoint,
  distanceMatrix,
} from "wakeb-map";

const meters = calculateDistance(
  { lat: 24.7136, lng: 46.6753 },
  { lat: 21.4225, lng: 39.8262 },
);

GeoJSON Import/Export

import { exportToGeoJSON, importFromGeoJSON, downloadGeoJSON } from "wakeb-map";

const geojson = exportToGeoJSON({ markers, polylines, polygons, circles });
const data = importFromGeoJSON(geojsonObject);
downloadGeoJSON(geojson, "my-map.geojson");

Props Reference

<WakebMap>

Prop Type Default Description
center WakebLatLng { lat: 24.7136, lng: 46.6753 } Map center
zoom number 14 Zoom level
mapType WakebMapType 'streets' Tile layer preset
provider string 'leaflet' Map provider ('leaflet'/'mapbox'/'google')
accessToken string — Mapbox access token
mapStyle string — Mapbox style URL
markers WakebMarker[] [] Marker array
polylines WakebPolyline[] [] Polyline array
circles WakebCircle[] [] Circle array
polygons WakebPolygon[] [] Polygon array
routes WakebRoute[] [] Route array
width string '100%' Container width
height string '400px' Container height
clickToAddMarker boolean false Click to place markers
markerColor string 'red' Default marker color
markerDraggable boolean true Click-to-add markers draggable
animateMarkers boolean false Smooth animated marker movement
showScale boolean false Scale control
showFullscreen boolean false Fullscreen button
showLayerSwitcher boolean false Layer switcher overlay
showGeolocation boolean false "My Location" button
showCoordinates boolean false Cursor coordinate display
showDrawingToolbar boolean false Drawing toolbar
cooperativeGestures boolean false Ctrl+scroll to zoom
keyboardNavigation boolean false Arrow key panning
hashRouting boolean false Sync state with URL hash
zoomControl boolean true Zoom buttons
options object {} Extra map options (provider-specific)

<WakebMapPicker>

Prop Type Default Description
v-model WakebLatLng — Selected location
mapType WakebMapType 'streets' Map style
showSearch boolean true Search input
showMyLocation boolean true GPS button
showAddress boolean true Address display
useCenterPin boolean true Center pin mode
showConfirmButton boolean true Confirm button
confirmLabel string 'Confirm Location' Button text

Events

<WakebMap>

Event Payload Description
click { position, originalEvent } Map click
markerClick WakebMarker Marker click
markerDragEnd (marker, newPosition) Marker drag end
markerDragStart WakebMarker Marker drag start
markerAdded WakebMarker Marker added (click-to-add)
markerRemoved markerId Marker removed
cameraChange WakebCameraPosition Viewport change
mapReady native map instance Map initialized
providerReady WakebMapProviderInstance Provider instance ready
drawComplete WakebDrawnPath | WakebDrawnShape | WakebMeasurement Drawing finished
drawUpdate same Drawing updated
geolocation WakebLatLng User location acquired
update:center WakebLatLng Center changed
update:zoom number Zoom changed

<WakebMapPicker>

Event Payload Description
update:modelValue WakebLatLng Location updated
locationPicked { position, address } Location confirmed

Documentation

Full interactive docs with live demos:

visit the hosted docs at wakeb-map.surge.sh


License

MIT © Kerolos Zakaria

Related Packages

vue-mapbox-ts

Reactive Vue3 Mapbox Framework for Vue.js written in TypeScript

194,679
mapvue

MapVue is a comprehensive MapboxGL component library. You can easily and happily...

1,247 22
vue-use-leaflet

Vue composition utilities for leaflet map

15,495 5
vue2mapbox-gl

Vue >2 integration of mapbox.

2,231 19
vue-leaflet-markercluster

Leaflet markercluster components for Vue.js, based on leaflet.markercluster.

278,849 48

Version History

Version Released Vue License
2.3.0 ^3.3.0 MIT
2.2.1 ^3.3.0 MIT
2.2.0 ^3.3.0 MIT
2.1.9 ^3.3.0 MIT
2.1.8 ^3.3.0 MIT