A minimal, production-ready drawing library for MapLibre GL JS with line, dashed line, freehand, polygon, and select modes with multiple color support
npm install maplibre-gl-multiple-color-drawA production-ready drawing library for MapLibre GL JS. Draw lines, polygons, and freehand shapes on maps with multiple colors, dynamic styling, and full GeoJSON support.
- 6 Drawing Modes: Line, Dashed Line, Freehand, Freehand Dashed, Polygon, and Select/Move
- Simple API: Clean, intuitive interface with TypeScript support
- GeoJSON Export: All features stored as standard GeoJSON
- Dynamic Styling: Change color and thickness at runtime
- React Hook: Built-in useMapDraw hook for React applications
- Lightweight: Zero dependencies (only peer dependency: maplibre-gl)
- Type Safe: Full TypeScript definitions included
- Framework Agnostic: Works with any JavaScript framework
``bash`
npm install maplibre-gl-multiple-color-draw
Peer Dependencies:
`bash`
npm install maplibre-gl

Here's a complete example that demonstrates all features. The styling uses Tailwind CSS classes, but you can replace them with inline styles or any CSS framework:
`tsx
import { useEffect, useRef, useState } from "react";
import maplibregl, { Map as MaplibreMap } from "maplibre-gl";
import { useMapDraw } from "maplibre-gl-multiple-color-draw";
import "maplibre-gl/dist/maplibre-gl.css";
function MapDrawComponent() {
const mapContainer = useRef
const mapRef = useRef
const [map, setMap] = useState
const [color, setColorState] = useState("#3388ff");
const [thickness, setThicknessState] = useState(2);
// Initialize map
useEffect(() => {
if (!mapContainer.current || mapRef.current) return;
const newMap = new maplibregl.Map({
container: mapContainer.current,
style: "https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json",
center: [0, 0],
zoom: 2,
});
mapRef.current = newMap;
setMap(newMap);
return () => {
newMap.remove();
mapRef.current = null;
};
}, []);
// Initialize drawing
const { enable, setMode, setColor, setThickness, getGeoJSON, clear } =
useMapDraw(map, {
color,
thickness,
});
// Enable drawing when map is ready
useEffect(() => {
if (map) enable();
}, [map, enable]);
const handleColorChange = (e: React.ChangeEvent
const newColor = e.target.value;
setColorState(newColor);
setColor(newColor);
};
const handleThicknessChange = (e: React.ChangeEvent
const value = Number(e.target.value);
setThicknessState(value);
setThickness(value);
};
const handleExport = () => {
const geoJSON = getGeoJSON();
const blob = new Blob([JSON.stringify(geoJSON, null, 2)], {
type: "application/json",
});
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "map-drawing.geojson";
a.click();
URL.revokeObjectURL(url);
};
const btn =
"px-3 py-1.5 rounded-md border border-gray-300 text-sm font-medium text-gray-700 bg-white hover:bg-gray-50";
return (
export default MapDrawComponent;
`
Usage in your App:
`tsx
import MapDrawComponent from "./MapDrawComponent";
function App() {
return (
export default App;
`
#### Constructor
`typescript`
new MapDraw(map: Map, options?: MapDrawOptions)
Parameters:
- map (Map): A MapLibre GL Map instanceoptions
- (MapDrawOptions, optional): Configuration options
Options:
- color?: string - Default line/fill color (default: '#3388ff')thickness?
- : number - Default line thickness in pixels (default: 2)dashArray?
- : number[] - Dash pattern for dashed lines (default: [5, 5])defaultMode?
- : DrawMode - Initial mode when enabled (default: 'line')enabled?
- : boolean - Auto-enable on creation (default: false)
#### Methods
##### enable(): void
Enables drawing on the map. Must be called before drawing can begin (unless enabled: true in options).
##### disable(): void
Disables drawing and stops all interactions. Features remain on the map but cannot be modified.
##### setMode(mode: DrawMode): void
Changes the active drawing mode. Available modes:
- 'line' - Click to place points, double-click to finish
- 'dashed-line' - Same as line but with dash pattern
- 'freehand' - Click once to start, move mouse to draw, click again to finish
- 'freehand-dashed' - Freehand drawing with dashed line style
- 'polygon' - Click to place vertices, double-click or right-click to finish
- 'select' - Click to select features, drag to move selected features
##### setColor(color: string): void
Updates the color for new features. Accepts any valid CSS color (hex, rgb, rgba, named colors).
##### setThickness(thickness: number): void
Updates the line thickness for new features (in pixels).
##### getFeatures(): DrawFeature[]
Returns all drawn features as an array of DrawFeature objects.
##### getGeoJSON(): GeoJSON
Returns all features as a standard GeoJSON FeatureCollection, ready for export or API submission.
##### clear(): void
Removes all drawn features from the map.
##### destroy(): void
Completely cleans up all resources, removes layers, event listeners, and disables drawing. Call this when unmounting your component or removing the map.
For React applications, use the useMapDraw hook:
`typescript
import { useMapDraw } from "maplibre-gl-multiple-color-draw";
const {
mapDraw, // MapDraw instance (null until map is ready)
enable, // Enable drawing
disable, // Disable drawing
setMode, // Change mode
setColor, // Update color
setThickness, // Update thickness
getFeatures, // Get all features
getGeoJSON, // Get GeoJSON
clear, // Clear all drawings
} = useMapDraw(map, {
color: "#3388ff",
thickness: 2,
});
`
Parameters:
- map: Map | null - MapLibre GL Map instance (can be null initially)options?
- : MapDrawOptions - Same options as MapDraw constructor
Returns:
An object containing all MapDraw methods plus the mapDraw instance.
Full TypeScript definitions are included:
`typescript``
import type {
DrawMode,
DrawFeature,
MapDrawOptions,
} from "maplibre-gl-multiple-color-draw";
- GitHub: View on GitHub
- NPM Package: View on NPM
Works with all modern browsers that support:
- ES6+ JavaScript
- MapLibre GL JS (^3.0.0 or ^4.0.0)
MIT
Contributions are welcome! Please feel free to submit a Pull Request.