Skip to content

Leaflet makes it easy to take spatial lines and shapes from R and add them to maps.

Polygons and Polylines

Line and polygon data can come from a variety of sources:

  • SpatialPolygons, SpatialPolygonsDataFrame, Polygons, and Polygon objects (from the sp package)
  • SpatialLines, SpatialLinesDataFrame, Lines, and Line objects (from the sp package)
  • MULTIPOLYGON, POLYGON, MULTILINESTRING, and LINESTRING objects (from the sf package)
  • map objects (from the maps package’s map() function); use map(fill = TRUE) for polygons, FALSE for polylines
  • Two-column numeric matrix; the first column is longitude and the second is latitude. Polygons are separated by rows of (NA, NA). It is not possible to represent multi-polygons nor polygons with holes using this method; use SpatialPolygons instead.
# From
states <- sf::st_read("shp/cb_2013_us_state_20m.shp",
  layer = "cb_2013_us_state_20m")
#> Reading layer `cb_2013_us_state_20m' from data source 
#>   `/home/runner/work/leaflet/leaflet/vignettes/articles/shp/cb_2013_us_state_20m.shp' 
#>   using driver `ESRI Shapefile'
#> Simple feature collection with 52 features and 9 fields
#> Geometry type: MULTIPOLYGON
#> Dimension:     XY
#> Bounding box:  xmin: -179.1473 ymin: 17.88481 xmax: 179.7785 ymax: 71.35256
#> Geodetic CRS:  NAD83

neStates <- subset(states, states$STUSPS %in% c(

leaflet(neStates) %>%
  addPolygons(color = "#444444", weight = 1, smoothFactor = 0.5,
    opacity = 1.0, fillOpacity = 0.5,
    fillColor = ~colorQuantile("YlOrRd", ALAND)(ALAND),
    highlightOptions = highlightOptions(color = "white", weight = 2,
      bringToFront = TRUE))

Highlighting shapes

The above example uses the highlightOptions parameter to emphasize the currently moused-over polygon. (The bringToFront = TRUE argument is necessary to prevent the thicker, white border of the active polygon from being hidden behind the borders of other polygons that happen to be higher in the z-order.) You can use highlightOptions with all of the shape layers described on this page.

Simplifying complex polygons/polylines

Very detailed (i.e. large) shape data can present a problem for Leafet, since it is all eventually passed into the browser and rendered as SVG, which is very expressive and convenient but has scalability limits. In these cases, consider using rmapshaper::ms_simplify, which does topology-preserving simplification conveniently from R.

library(albersusa) # Requires rgdal, archived.

fullsize <- usa_sf()

simplified <- rmapshaper::ms_simplify(fullsize)


Circles are added using addCircles(). Circles are similar to circle markers; the only difference is that circles have their radii specified in meters, while circle markers are specified in pixels. As a result, circles are scaled with the map as the user zooms in and out, while circle markers remain a constant size on the screen regardless of zoom level.

When plotting circles, only the circle centers (and radii) are required, so the set of valid data sources is different than for polygons and the same as for markers. See the introduction to Markers for specifics.

cities <- read.csv(textConnection("
New York City,40.7127,-74.0059,8406000

leaflet(cities) %>% addTiles() %>%
  addCircles(lng = ~Long, lat = ~Lat, weight = 1,
    radius = ~sqrt(Pop) * 30, popup = ~City


Rectangles are added using the addRectangles() function. It takes lng1, lng2, lat1, and lat2 vector arguments that define the corners of the rectangles. These arguments are always required; the rectangle geometry cannot be inferred from the data object.

leaflet() %>% addTiles() %>%
    lng1=-118.456554, lat1=34.078039,
    lng2=-118.436383, lat2=34.062717,
    fillColor = "transparent"