ng-simple-maps

January 18, 2026 Β· View on GitHub

npm version Build Status License: MIT Angular TypeScript

Beautiful, lightweight SVG world maps for Angular applications. Create stunning interactive choropleth maps, data visualizations, geographic dashboards, and analytics with D3 geo projections. Perfect for business intelligence, travel apps, educational tools, and corporate websites.

πŸš€ Live Demo & Documentation

View Interactive Demo β†’

Angular Version Support

This library supports Angular 15+.

Peer Dependencies: @angular/core@>=15.0.0 and @angular/common@>=15.0.0

πŸ—ΊοΈ World Map Library | πŸ“Š Data Visualization | 🌍 Geographic Mapping | πŸ“± Responsive Design | ⚑ Interactive Maps

Features

  • One Simple Component - Everything you need in <asm-map>
  • Data-Driven - Pass arrays of markers, annotations, and lines
  • Lines/Connections - Draw curved flight paths between points
  • Choropleth Maps - Color countries by data values
  • Country Labels - Show country names with zoom-based visibility
  • Zoom to Feature - Click countries to zoom and center on them
  • Graticule Grid - Latitude/longitude grid lines
  • Zoom & Pan - Enable with a single property
  • Tooltips - Automatic on hover, fully customizable
  • 15+ Projections - Mercator, Equal Earth, Orthographic, and more
  • Continent Filtering - Show only the regions you need
  • Multiple Marker Shapes - Circle, diamond, pin, star
  • Fully Responsive - Scales to any screen size
  • TypeScript - Full type safety

Installation

npm install ng-simple-maps

Quick Start

import { Component } from '@angular/core';
import { MapComponent } from 'ng-simple-maps';

@Component({
  imports: [MapComponent],
  template: `
    <asm-map
      [geography]="worldData"
      [zoomable]="true"
      [showTooltip]="true">
    </asm-map>
  `
})
export class MyComponent {
  worldData = 'https://cdn.jsdelivr.net/npm/world-atlas@2/countries-110m.json';
}

That's it! You have a fully interactive world map with zoom, pan, and tooltips.

Examples

With Markers

import { MapComponent, MapMarker } from 'ng-simple-maps';

@Component({
  imports: [MapComponent],
  template: `
    <asm-map
      [geography]="worldData"
      [markers]="markers"
      [zoomable]="true"
      [showTooltip]="true"
      (markerClick)="onMarkerClick($event)">
    </asm-map>
  `
})
export class MyComponent {
  worldData = 'https://cdn.jsdelivr.net/npm/world-atlas@2/countries-110m.json';

  markers: MapMarker[] = [
    { coordinates: [-74.006, 40.7128], label: 'New York', color: '#FF5533' },
    { coordinates: [2.3522, 48.8566], label: 'Paris', color: '#FFD700', size: 8 },
    { coordinates: [37.6173, 55.7558], label: 'Moscow', shape: 'diamond' }
  ];

  onMarkerClick(event) {
    console.log('Clicked:', event.marker.label);
  }
}

With Annotations

markers: MapMarker[] = [
  { coordinates: [-74.006, 40.7128], label: 'New York' }
];

annotations: MapAnnotation[] = [
  { coordinates: [-74.006, 40.7128], text: 'New York', dx: 50, dy: -30, curve: 0.5 }
];
<asm-map
  [geography]="worldData"
  [markers]="markers"
  [annotations]="annotations">
</asm-map>

Continent Filtering

<!-- Single continent -->
<asm-map [geography]="worldData" continents="Europe"></asm-map>

<!-- Multiple continents -->
<asm-map [geography]="worldData" [continents]="['Asia', 'Europe']"></asm-map>

Custom Styling

<asm-map
  [geography]="worldData"
  fill="#457B9D"
  stroke="#1D3557"
  hoverFill="#2A4D6E"
  [tooltipConfig]="{ backgroundColor: '#1D3557', textColor: '#fff' }">
</asm-map>

Different Projections

<!-- Globe view -->
<asm-map [geography]="worldData" projection="geoOrthographic"></asm-map>

<!-- Mercator -->
<asm-map [geography]="worldData" projection="geoMercator"></asm-map>

<!-- Rotated orthographic (custom view) -->
<asm-map 
  [geography]="worldData" 
  projection="geoOrthographic"
  [projectionConfig]="{ rotate: [-10, -20] }">
</asm-map>

<!-- Centered on Asia -->
<asm-map 
  [geography]="worldData" 
  projection="geoEqualEarth"
  [projectionConfig]="{ center: [100, 30] }">
</asm-map>

Lines/Connections (Flight Paths)

import { MapComponent, MapLine } from 'ng-simple-maps';

lines: MapLine[] = [
  { from: [-74.006, 40.7128], to: [-0.1276, 51.5074], color: '#E91E63', curve: 0.4 },
  { from: [-74.006, 40.7128], to: [139.6917, 35.6895], color: '#3F51B5', curve: 0.5, dashed: true }
];
<asm-map
  [geography]="worldData"
  [lines]="lines"
  (lineClick)="onLineClick($event)">
</asm-map>

Choropleth Maps (Data Coloring)

import { MapComponent, ChoroplethData } from 'ng-simple-maps';

populationData: ChoroplethData = {
  'United States of America': 330,
  'China': 1400,
  'India': 1380,
  'Brazil': 212
};
<asm-map
  [geography]="worldData"
  [choroplethData]="populationData"
  [choroplethConfig]="{
    matchKey: 'name',
    colors: ['#FFF3E0', '#FFCC80', '#FFA726', '#F57C00', '#E65100'],
    nullColor: '#ECECEC'
  }">
</asm-map>

Graticule (Grid Lines)

<asm-map
  [geography]="worldData"
  projection="geoOrthographic"
  [showGraticule]="true"
  [graticuleConfig]="{ step: [15, 15], color: '#B3E5FC', opacity: 0.8 }">
</asm-map>

Country Labels

<asm-map
  [geography]="worldData"
  [showLabels]="true"
  [labelMinZoom]="2"
  [labelColor]="'#333'"
  [labelFontSize]="14"
  [zoomable]="true">
</asm-map>

Zoom to Feature

<asm-map
  [geography]="worldData"
  [zoomable]="true"
  [zoomOnClick]="true"
  [zoomOnClickLevel]="4"
  [zoomAnimationDuration]="1000">
</asm-map>

API Reference

MapComponent Inputs

InputTypeDefaultDescription
geographystring | objectrequiredGeography data URL or TopoJSON/GeoJSON object
widthnumber800Map width (for aspect ratio)
heightnumber400Map height (for aspect ratio)
maxWidthnumbernullMaximum width constraint
projectionstring'geoEqualEarth'D3 projection type
projectionConfigProjectionConfig{}Projection configuration options
continentsstring | string[]nullFilter by continent(s)
fillstring'#ECECEC'Geography fill color
strokestring'#D6D6D6'Geography stroke color
strokeWidthnumber0.5Geography stroke width
hoverFillstringnullFill color on hover
markersMapMarker[][]Array of markers
annotationsMapAnnotation[][]Array of annotations
markerColorstring'#FF5533'Default marker color
markerSizenumber6Default marker size
linesMapLine[][]Array of lines/connections
lineColorstring'#FF5533'Default line color
lineStrokeWidthnumber2Default line stroke width
choroplethDataChoroplethDatanullData for coloring geographies
choroplethConfigChoroplethConfignullChoropleth styling config
showGraticulebooleanfalseShow grid lines
graticuleConfigGraticuleConfignullGraticule styling config
zoomablebooleanfalseEnable zoom and pan
showZoomControlsbooleantrueShow zoom buttons
minZoomnumber1Minimum zoom level
maxZoomnumber8Maximum zoom level
zoomOnClickbooleanfalseZoom to country on click
zoomOnClickLevelnumber4Zoom level when clicking country
zoomAnimationDurationnumber800Animation duration in milliseconds
showTooltipbooleanfalseShow tooltip on hover
tooltipConfigTooltipConfignullTooltip styling
showLabelsbooleanfalseShow country labels
labelMinZoomnumber1Minimum zoom level to show labels
labelFontSizenumber12Label font size
labelColorstring'#333'Label text color
labelFontWeightstring | number'normal'Label font weight

MapComponent Outputs

OutputTypeDescription
countryClickMapGeographyEventEmitted when a country is clicked
countryHoverMapGeographyEventEmitted when hovering over a country
countryLeavevoidEmitted when mouse leaves a country
markerClickMapMarkerEventEmitted when a marker is clicked
lineClickMapLineEventEmitted when a line is clicked

MapMarker Interface

interface MapMarker {
  coordinates: [number, number];  // [longitude, latitude]
  label?: string;                 // Optional label
  color?: string;                 // Fill color
  stroke?: string;                // Stroke color
  size?: number;                  // Size/radius (6-12 for icons, 16-24 for detailed SVGs)
  shape?: 'circle' | 'diamond' | 'pin' | 'star' | 'custom';
  customSvg?: string;             // SVG path data for shape='custom'
  customSvgSize?: number;         // ViewBox size for custom SVG (default: 24)
  data?: Record<string, unknown>; // Custom data
}

Custom SVG Markers

Three ways to use custom SVG icons as markers:

Just the d attribute value - most lightweight:

const AIRPLANE = 'M21,16V14L13,9V3.5A1.5,1.5,0,0,0,11.5,2...Z';

markers: MapMarker[] = [
  { coordinates: [-118.24, 34.05], shape: 'custom', customSvg: AIRPLANE, size: 10 }
];

Option 2: Full SVG Markup

For complex icons with multiple elements:

const PIN = `<svg viewBox="0 0 24 24">
  <path d="M12,2C8.13,2,5,5.13,5,9c0,5.25,7,13,7,13s7-7.75,7-13C19,5.13,15.87,2,12,2z"/>
  <circle cx="12" cy="9" r="2.5" fill="white"/>
</svg>`;

markers: MapMarker[] = [
  { coordinates: [121.47, 31.23], shape: 'custom', customSvg: PIN, size: 12 }
];

Option 3: Load from URL

Load SVG files from your assets folder:

markers: MapMarker[] = [
  { coordinates: [0, 0], shape: 'custom', customSvgUrl: '/assets/icons/marker.svg', size: 12 }
];

SVG Size Guidelines:

Use CasesizeDescription
Small icons6-8Simple shapes
Standard10-12Recommended
Large/detailed14-18Fine details
Icon SetcustomSvgSize
Material Design24 (default)
Font Awesome24
Custom 16px16

MapAnnotation Interface

interface MapAnnotation {
  coordinates: [number, number];  // [longitude, latitude]
  text: string;                   // Label text
  dx?: number;                    // Horizontal offset (default: 30)
  dy?: number;                    // Vertical offset (default: -30)
  curve?: number;                 // Connector curve (0-1, default: 0)
  color?: string;                 // Text and connector color
  fontSize?: number;              // Font size
  fontWeight?: string | number;   // Font weight
}

TooltipConfig Interface

interface TooltipConfig {
  backgroundColor?: string;  // Default: '#fff'
  textColor?: string;        // Default: '#333'
  titleColor?: string;       // Default: same as textColor
  borderColor?: string;      // Default: '#ccc'
  borderRadius?: number;     // Default: 4
}

MapLine Interface

interface MapLine {
  from: [number, number];    // Starting [longitude, latitude]
  to: [number, number];      // Ending [longitude, latitude]
  color?: string;            // Line color
  strokeWidth?: number;      // Line thickness
  curve?: number;            // Arc height (0 = straight, higher = more curved)
  dashed?: boolean;          // Dashed line style
  data?: Record<string, unknown>; // Custom data
}

ChoroplethConfig Interface

interface ChoroplethConfig {
  matchKey?: string;      // Property to match (default: 'name')
  colors?: string[];      // Color scale from low to high
  minValue?: number;      // Override minimum value
  maxValue?: number;      // Override maximum value
  nullColor?: string;     // Color for missing data (default: '#ECECEC')
}

GraticuleConfig Interface

interface GraticuleConfig {
  step?: [number, number];  // Grid spacing in degrees (default: [10, 10])
  color?: string;           // Line color (default: '#ccc')
  strokeWidth?: number;     // Line thickness (default: 0.5)
  opacity?: number;         // Line opacity (default: 0.5)
}

ProjectionConfig Interface

interface ProjectionConfig {
  rotate?: [number, number, number?];  // Rotation angles [lambda, phi, gamma] in degrees
  center?: [number, number];           // Center coordinates [longitude, latitude]
  scale?: number;                      // Scale factor for the projection
  parallels?: [number, number];        // Standard parallels for conic projections
  translate?: [number, number];        // Translation offset [x, y]
  precision?: number;                  // Precision threshold for adaptive resampling
  clipAngle?: number;                  // Clipping angle for azimuthal projections
}

Available Projections

  • geoEqualEarth (default)
  • geoMercator
  • geoOrthographic
  • geoNaturalEarth1
  • geoAlbers
  • geoAlbersUsa
  • geoAzimuthalEqualArea
  • geoAzimuthalEquidistant
  • geoConicConformal
  • geoConicEqualArea
  • geoConicEquidistant
  • geoEquirectangular
  • geoGnomonic
  • geoStereographic
  • geoTransverseMercator

Continent Options

  • 'Africa'
  • 'Asia'
  • 'Europe'
  • 'North America'
  • 'South America'
  • 'Oceania'
  • 'Antarctica'

TopoJSON Data Sources

Free, high-quality world country data maintained by Mike Bostock. Choose the right resolution for your use case:

// Fast loading (13KB) - for mobile apps and overview maps
worldData = 'https://cdn.jsdelivr.net/npm/world-atlas@2/countries-110m.json';

// Balanced quality (23KB) - recommended for web apps
worldData = 'https://cdn.jsdelivr.net/npm/world-atlas@2/countries-50m.json';

// High detail (94KB) - for detailed maps and print quality
worldData = 'https://cdn.jsdelivr.net/npm/world-atlas@2/countries-10m.json';

Resolution Guide

ResolutionFile SizeUse CaseBest For
110m13KBFast loadingMobile apps, overview maps, low bandwidth
50m23KBRecommendedWeb applications, general purpose
10m94KBHigh detailDesktop apps, print quality, detailed viewing

Available Files

  • countries-110m.json - Low resolution, fast loading
  • countries-50m.json - Medium resolution, balanced (used in all demos)
  • countries-10m.json - High resolution, detailed

Other Data Sources

Local Files

You can also download and serve TopoJSON files from your own assets folder:

// From local assets
worldData = '/assets/data/countries-50m.json';

License

MIT

Credits

Inspired by react-simple-maps. Built with D3 Geo.