leaflet绘制地图

R语言
地图
可视化
leaflet包介绍
作者

不止BI

发布于

2024年4月1日

leaflet包是R语言中一个用于创建交互式地图的强大工具包。它基于Leaflet JavaScript库,可以轻松创建具有各种功能的地图,例如:

添加图层,如底图、标记、线、面等 控制地图的缩放、平移、旋转等操作 添加交互式控件,如搜索、图层控制等 支持多种地图类型,如 OpenStreetMap、Google Maps、高德地图等

基本用法

生成图层

library(leaflet)
library(leafletCN)
library(leaflet.extras)
library(tidyverse)
m <- leaflet() %>%
  # 添加高德地图底图
  amap(group = "高德") %>%
  # 设置地图中心和缩放级别
  setView(
    lng = 121.33739,
    lat = 31.13533,
    zoom = 12
  )
m

添加测距工具

m <- m %>% addMeasure(localization = "cn", primaryLengthUnit = "kilometers", secondaryLengthUnit = "meters")
m
测量

添加地点图标

df_home_location <- tribble(
  ~Name, ~WGS84Longitude, ~WGS84Latitude,
  "地点1", 121.33739, 31.13533,
  "地点2", 121.33539, 31.15533
)
m <- m %>%
  addAwesomeMarkers(
    lng = ~WGS84Longitude,
    lat = ~WGS84Latitude,
    label = ~Name,
    popup = ~Name,
    group = "home",
    icon = awesomeIcons(icon = "home"),
    data = df_home_location,
    clusterOptions = markerClusterOptions(),
    clusterId = "storeCluster"
  )
m
2
测量

添加地点半径范围

m <- m %>% addCircles(
  lng = ~WGS84Longitude,
  lat = ~WGS84Latitude,
  radius = 2000,
  label = ~Name,
  popup = ~Name,
  group = "home2km",
  data = df_home_location
)
m
2
测量

添加新的图标图层

df_car <- tribble(
  ~Car, ~WGS84Longitude, ~WGS84Latitude, ~CarNo,
  "车辆1", 121.33439, 31.14533, "车牌1",
  "车辆2", 121.33039, 31.10533, "车牌2"
)
df_car <- df_car %>% mutate(info = str_c(Car, CarNo, sep = "<br/>"))
m <- m %>% addAwesomeMarkers(
  lng = ~WGS84Longitude,
  lat = ~WGS84Latitude,
  # label = ~ info,
  label = ~CarNo,
  popup = ~info,
  group = "car",
  # clusterOptions = markerClusterOptions(),
  # clusterId = "carCluster",
  icon = awesomeIcons(icon = "automobile", library = "fa", markerColor = "orange"),
  data = df_car
)
m
2
测量

添加搜索功能

m <- m %>% addSearchFeatures(targetGroups = "home")
m
2
测量

添加图层控制

m <- m %>% addLayersControl(
  baseGroups = "home",
  overlayGroups = c("car", "home", "home2km")
)
m
2
测量

添加小地图

m <- m %>%
  addMiniMap()
m
2
测量

形状地图

从geoJson读取形状

省份地图

library(geojson)
filePath <- system.file("geojson/china.json", package = "leafletCN")
china_geo_shape <- read.geoShape(filePath)
## 在geojson中加入自定义数据
china_geo_shape$randvalue <- runif(length(china_geo_shape$name), 0, 100)
china_geojson <- as.geojson(china_geo_shape)

leaflet() %>%
  addTiles() %>%
  setView(
    lng = 120.33739,
    lat = 31.13533, zoom = 3
  ) %>%
  amap() %>%
  addBootstrapDependency() %>%
  enableMeasurePath() %>%
  addGeoJSONChoropleth(
    china_geojson,
    valueProperty = "randvalue",
    labelProperty = "name",
    popupProperty = propstoHTMLTable(
      props = c("name", "size", "childNum", "randvalue"),
      table.attrs = list(class = "table table-striped table-bordered"),
      drop.na = TRUE
    ),
    color = "#ffffff", weight = 1, fillOpacity = 0.7,
    highlightOptions = highlightOptions(
      weight = 2, color = "#000000",
      fillOpacity = 1, opacity = 1,
      bringToFront = TRUE, sendToBack = TRUE
    )
  ) %>%
  addPulseMarkers(
    lng = 116.4551, lat = 40.2539,
    label = "This is a label",
    icon = makePulseIcon(heartbeat = 0.5)
  )

城市地图

filePath <- system.file("geojson/city.json", package = "leafletCN")
city_geo_shape <- read.geoShape(filePath)
## 在geojson中加入自定义数据
city_geo_shape$randvalue <- runif(length(city_geo_shape$name), 0, 100)
city_geojson <- as.geojson(city_geo_shape)

city_geo_map <- leaflet() %>%
  addTiles() %>%
  setView(
    lng = 120.33739,
    lat = 31.13533, zoom = 3
  ) %>%
  amap() %>%
  addBootstrapDependency() %>%
  enableMeasurePath() %>%
  addGeoJSONChoropleth(
    city_geojson,
    valueProperty = "randvalue",
    labelProperty = "name",
    popupProperty = propstoHTMLTable(
      props = c("id", "name", "randvalue"),
      table.attrs = list(class = "table table-striped table-bordered"),
      drop.na = TRUE
    ),
    color = "#ffffff", weight = 1, fillOpacity = 0.7,
    highlightOptions = highlightOptions(
      weight = 2, color = "#000000",
      fillOpacity = 1, opacity = 1,
      bringToFront = TRUE, sendToBack = TRUE
    ), popupOptions = popupOptions(noHide = TRUE)
  ) %>%
  addFullscreenControl() %>%
  addDrawToolbar(
    targetGroup = "draw",
    editOptions = editToolbarOptions(
      selectedPathOptions = selectedPathOptions()
    )
  ) %>%
  addLayersControl(
    overlayGroups = c("draw"),
    options = layersControlOptions(collapsed = FALSE)
  ) %>%
  addStyleEditor()
city_geo_map

热力地图

df_location <- tribble(
  ~Name, ~WGS84Longitude, ~WGS84Latitude, ~value,
  "地点1", 121.33739, 31.13533, 100,
  "地点2", 121.33539, 31.15533, 300
)
leaflet(df_location) %>%
  # 添加高德地图底图
  amap(group = "高德") %>%
  # 设置地图中心和缩放级别
  setView(
    lng = 121.33739,
    lat = 31.13533,
    zoom = 12
  ) %>%
  addHeatmap(
    lng = ~WGS84Longitude, lat = ~WGS84Latitude, intensity = ~value,
    blur = 20, max = 0.05, radius = 15
  )

轨迹地图

# 生成轨迹数据
latlngs <- data.frame(lng = sort(rnorm(
  n = 100, mean = 120.33739, sd = 0.1
)), lat = sort(rnorm(
  n = 100, mean = 31.13533, sd = 0.1
)))

leaflet() %>%
  amap(group = "高德") %>%
  setView(lng = 120.33739, lat = 31.13533, zoom = 10) %>%
  addPolylines(
    data = latlngs,
    lng = ~lng,
    lat = ~lat,
    color = "blue",
    weight = 5,
    dashArray = "5,10" # 设置虚线
  )

leafletZH

leafletZH是基于leaflet的扩展包,提供了中国瓦片地图图层、坐标系转换,添加形状地图图层及计算坐标覆盖面积的功能

添加中国图层

addTilesAmap可以直接添加高德图层到leaflet

library(leaflet)
library(leafletZH)
leaflet() %>%
  addTilesAmap() %>%
  setView(
    lng = 120.33739,
    lat = 31.13533,
    zoom = 3
  )

坐标转换

convertCoordinates提供了 WGS-84,GCJ-02,BD-09 坐标系坐标的互转功能。高德地图的坐标系为GCJ-02,在使用addTilesAmap添加的高德上绘制坐标,必须要先将坐标转为GCJ-02的坐标。

# Convert WGS-84 coordinates to GCJ-02
convertCoordinates(39.90105, 116.42079, from = "WGS-84", to = "GCJ-02")
[1]  39.90245 116.42702
# Convert GCJ-02 coordinates to BD-09
convertCoordinates(39.90245, 116.42702, "GCJ-02", "WGS-84")
[1]  39.90105 116.42079
# Convert WGS-84 coordinates to BD-09
convertCoordinates(39.90105, 116.42079, "WGS-84", "BD-09")
[1]  39.9085 116.4335

添加形状地图

leafletZH::china_provinceleafletZH::china_city分别提供了中国的城市及省份地图形状数据

leafletZH::china_province %>%
  head() %>%
  as_tibble()
# A tibble: 6 × 10
  adcode childrenNum level subFeatureIndex name  centroid center parent acroutes
  <chr>        <dbl> <chr>           <dbl> <chr> <chr>    <chr>  <chr>  <chr>   
1 110000          16 prov…               0 北京市…… [116.41… [116.… "{\"a… [100000]
2 120000          16 prov…               1 天津市…… [117.34… [117.… "{\"a… [100000]
3 130000          11 prov…               2 河北省…… <NA>     [114.… "{\"a… [100000]
4 140000          11 prov…               3 山西省…… [112.30… [112.… "{\"a… [100000]
5 150000          12 prov…               4 内蒙古自… [114.07… [111.… "{\"a… [100000]
6 210000          14 prov…               5 辽宁省…… [122.60… [123.… "{\"a… [100000]
# ℹ 1 more variable: geometry <MULTIPOLYGON [°]>
leafletZH::china_city %>% head()
Simple feature collection with 6 features and 9 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 116.0489 ymin: 39.76163 xmax: 116.6453 ymax: 40.16098
Geodetic CRS:  WGS 84
  adcode childrenNum    level subFeatureIndex     name               centroid
1 110101           0 district               0   东城区 [116.416718,39.912934]
2 110102           0 district               1   西城区  [116.36567,39.912028]
3 110105           0 district               2   朝阳区 [116.513687,39.951064]
4 110106           0 district               3   丰台区 [116.250342,39.835716]
5 110107           0 district               4 石景山区 [116.176229,39.933205]
6 110108           0 district               5   海淀区  [116.23328,40.026927]
                  center            parent        acroutes
1 [116.418757,39.917544] {"adcode":110000} [100000,110000]
2 [116.366794,39.915309] {"adcode":110000} [100000,110000]
3 [116.486409,39.921489] {"adcode":110000} [100000,110000]
4 [116.286968,39.863642] {"adcode":110000} [100000,110000]
5 [116.195445,39.914601] {"adcode":110000} [100000,110000]
6 [116.310316,39.956074] {"adcode":110000} [100000,110000]
                        geometry
1 MULTIPOLYGON (((116.4436 39...
2 MULTIPOLYGON (((116.3258 39...
3 MULTIPOLYGON (((116.5955 40...
4 MULTIPOLYGON (((116.2591 39...
5 MULTIPOLYGON (((116.167 39....
6 MULTIPOLYGON (((116.3258 39...

省份形状地图

通过addProvinceShapeaddCityShape可以分别绘制中国的省份形状地图和城市形状地图,绘制省份地图的时候可以用省份名称或adcode进行匹配数据。使用省份名称进行匹配,只使用省份的前两个字进行匹配,例如内蒙古、内蒙古自治区都可以成功匹配;若使用adcode数据进行匹配,可在leafletZH::china_province中查看对应省份的adcode数据。

library(leaflet)
library(leaflet.extras)
library(leafletZH)
data <- data.frame(name = leafletZH::china_province$name, value = runif(34))
backg <- htmltools::tags$style(".leaflet-container { background: #000; }")
leaflet() |>
  addProvinceShape(
    data = data, provinceName = "name", valueProperty = "value",
    popupProps = c("value")
  ) |>
  setView(lng = 110, lat = 40, zoom = 4) |>
  htmlwidgets::prependContent(backg)

城市形状地图

类似的,可以用adcode进行匹配,绘制城市形状地图,valueProperty参数可设置颜色深浅参数,popupProps设置点击工具提示内容

library(leaflet)
library(leaflet.extras)
library(leafletZH)
library(sf)
data <- data.frame(adcode = sample(leafletZH::china_city$adcode, 300), colorvalue = runif(300), tooltipvalue = runif(300))
leaflet() |>
  leafletZH::addTilesAmap() |>
  addCityShape(
    data = data, adcode = "adcode", valueProperty = "colorvalue",
    popupProps = c("colorvalue", "tooltipvalue")
  ) |>
  setView(lng = 116, lat = 40, zoom = 4)

坐标覆盖面积

areaCalculator可以计算提供坐标点位的覆盖面积,chull=T表示计算覆盖坐标列表的最小凸多边形

area <- areaCalculator(
  latitude = c(39.916, 39.919, 39.917),
  longitude = c(116.404, 116.407, 116.409),
  coordinate = "WGS-84"
)

area
[1] 56957.86

addAreaPolygons绘制坐标覆盖坐标列表的最小凸多边形形状

library(leaflet)
leaflet() %>%
  addTilesAmap() %>%
  addAreaPolygons(
    longitude = c(116.404, 116.407, 116.409),
    latitude = c(39.916, 39.919, 39.917), coordinate = "WGS-84"
  )
回到顶部