Note: This functionality is for advanced users and
may not be supported across all functions (for example,
addRasterImage()
currently works only with EPSG:3857 Web
Mercator).
The Leaflet package expects all point, line, and shape data to be specified in latitude and longitude using WGS 84 (a.k.a. EPSG:4326). By default, when displaying this data it projects everything to EPSG:3857 and expects that any map tiles are also displayed in EPSG:3857.
For users that need to display data with a different projection, we’ve integrated the Proj4Leaflet plugin, which in theory gives Leaflet access to any CRS that is supported by Proj4js.
Note that whatever map tiles you use must be designed to work with the CRS of your Leaflet map.
Defining a custom CRS
Once you’ve decided on a custom projection, and have map tiles to
match it (if necessary), you can use leafletCRS()
to create
a custom projection.
crs <- leafletCRS(crsClass = "L.Proj.CRS", code = "ESRI:102003",
proj4def = "+proj=aea +lat_1=29.5 +lat_2=45.5 +lat_0=37.5 +lon_0=-96 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs",
resolutions = 1.5^(25:15))
The crsClass
parameter lets you specify the JavaScript
constructor to use to generate the Leaflet.js CRS object. In this case,
we’re using L.Proj.CRS
, which is the class that comes with
Proj4Leaflet. (Only a specific list of CRS classes can be used here; see
?leafletCRS
for more details.)
The code
parameter is the CRS identifier, usually an
EPSG identifier or similar. (For the most part, this doesn’t affect us,
and you can treat it like documentation; it’s primarily used by
Proj4Leaflet for purposes that don’t apply to the R package.)
The proj4def
parameter is either a PROJ.4 or WKT string
that defines the CRS. If you don’t know the PROJ.4 or WKT string, you
can generally find these on epsg.io or spatialreference.org.
The resulting object can be passed to the leaflet
function via the parameter
crs = leafletOptions(crs = ...)
.
Displaying basemap tiles with custom projections
This example shows Gothenberg, Sweden in EPSG:3006 (SWEREF99 TM) projection.
epsg3006 <- leafletCRS(crsClass = "L.Proj.CRS", code = "EPSG:3006",
proj4def = "+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs",
resolutions = 2^(13:-1), # 8192 down to 0.5
origin = c(0, 0)
)
tile_url <- "http://api.geosition.com/tile/osm-bright-3006/{z}/{x}/{y}.png"
tile_attrib <- "Map data © <a href='http://www.openstreetmap.org/copyright'>OpenStreetMap contributors</a>, Imagery © 2013 <a href='http://www.kartena.se/'>Kartena</a>"
leaflet(options = leafletOptions(worldCopyJump = FALSE, crs = epsg3006)) %>%
setView(11.965053, 57.70451, 13) %>%
addTiles(urlTemplate = tile_url,
attribution = tile_attrib,
options = tileOptions(minZoom = 0, maxZoom = 14, continuousWorld = TRUE)) %>%
addMarkers(11.965053, 57.70451)
Again, it’s critical to use basemap tiles that are in the same
projection that is specified in leafletCRS()
. In this case
the api.geosition.com server does indeed uses EPSG:3006 for its
tiles.
We can render a similar map with the default EPSG:3857 projection for comparison. If the custom projection worked correctly, the markers should appear at the same position.
Displaying shapes with custom projections
While tiles must be in the same projection as used in
leafletCRS()
, you must always use WGS 84 longitude/latitude
data for markers, circles, polygons, and lines. Leaflet will
automatically project the coordinates when displaying.
This example uses data from the rnaturalearth package and projects it to the EPSG:9311 (US National Atlas Equal Area) coordinate system. Compare the first map, which uses the default CRS, to the second map, which is reprojected.
north_america <-
rnaturalearth::countries110 |>
dplyr::filter(CONTINENT == "North America")
epsg9311 <- leafletCRS(
crsClass = "L.Proj.CRS",
code = "EPSG:9311",
proj4def = "+proj=laea +lat_0=45 +lon_0=-100 +x_0=0 +y_0=0 +a=6370997 +b=6370997 +units=m +no_defs",
resolutions = 2 ^ (16:7)
)
pal <- leaflet::colorNumeric(palette = "viridis", domain = north_america$POP_EST)
plot_na_map <- function(opts = leafletOptions()) {
leaflet(north_america, options = opts) %>%
addPolygons(
weight = 1,
color = "#444444",
opacity = 1,
fillColor = ~ pal(POP_EST),
fillOpacity = 0.7,
smoothFactor = 0.5,
label = ~ paste(SOVEREIGNT, POP_EST),
labelOptions = labelOptions(direction = "auto")
)
}
plot_na_map()
plot_na_map(opts = leafletOptions(crs = epsg9311))