amitdar
amitdar

Reputation: 927

Use svg as map using leaflet.js

Is it possible to use SVG image as the base map for leaflet.js ?

In my case I have huge svg file and I wish to allow my users to use all of leaflet's features such as zoom, markers, layers.

Upvotes: 19

Views: 24981

Answers (2)

herrstrietzel
herrstrietzel

Reputation: 17205

Translate SVG to leaflet coordinates

In addition to Rob Imig's answer: you probably want to place markers relative to your svg coordinates.

Based on the official leaflet simple CRS example:

  1. check your SVG's intrinsic width/height or viewBox values
  2. apply these values to the bounds like so:
const bounds = [[0, 0], [svgHeight, svgWidth]];  

So we need to swap x/y order as explained by
IvanSanchez ("Leaflet+GeoJSON: Why are lat-lng coordinates in the wrong order?")

Leaflet uses lat-lng (or northing-easting)

const map = L.map('map', {
  crs: L.CRS.Simple,
  minZoom: -2,
  maxZoom: 20
});

const bounds = [
  [0, 0],
  [607, 756]
];
const image = L.imageOverlay('https://upload.wikimedia.org/wikipedia/commons/b/bb/Mayor_of_London_constituency_results_2000.svg', bounds).addTo(map);

var marker = L.marker([303.5, 378]).addTo(map);
marker.bindPopup("<b>Hello world!</b><br>I am a popup. SVG coordinates: x: 378; y:303.5").openPopup();


map.fitBounds(bounds);
html,
body {
  height: 100%;
  margin: 0;
}

.leaflet-container {
  width: 100%;
  max-width: 100%;
  max-height: 100%;
  aspect-ratio: 756/607;
}
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
<script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>

<div id='map'></div>

In the above example the intrinsic dimensions are:
width: 756
height: 607

We can place a marker at the horizontal and vertical center like so:

var marker = L.marker([ svgHeight/2, svgWidth/2]).addTo(map);  

Play around with codepen example

Upvotes: 1

Rob Imig
Rob Imig

Reputation: 496

Yes, you can just use imageOverlay, like this

// create the map
var map = L.map('map', {
  center: [40.75, -74.2],
  zoom: 13
});

var imageUrl = 'https://www.amcharts.com/lib/3/maps/svg/australiaHigh.svg',
  imageBounds = [
    [40.712216, -74.22655],
    [40.773941, -74.12544]
  ];

L.imageOverlay(imageUrl, imageBounds).addTo(map);
#map {
  height: 400px;
}
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
<div id="map"></div>

Upvotes: 23

Related Questions