0Pricing
R Academy · 课时

使用 leaflet 创建交互式地图

使用标记、弹出窗口和图块图层渲染交互式网络地图

使用 leaflet 创建交互式地图 是 CoddyKit 上的免费 R Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 R Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 R Academy 课程共包含 4 节课。

leaflet 简介

leaflet 软件包封装了 Leaflet.js 库,可以直接从 R 创建可交互、可缩放的网页地图。地图是 HTML 小部件,可在 RStudio 的 Viewer、R Markdown 和 Shiny 应用中渲染,无需了解 JavaScript。

library(leaflet)

# Minimal leaflet map: tiles + one marker
leaflet() |>
  addTiles() |>         # OpenStreetMap base layer
  setView(
    lng  = -74.006,
    lat  =  40.713,
    zoom = 12
  ) |>
  addMarkers(
    lng   = -74.006,
    lat   =  40.713,
    popup = '<b>New York City</b>'
  )

addTiles:底图图层

addTiles() 会添加默认的 OpenStreetMap 瓦片图层。使用 addProviderTiles(providers$) 可以切换到卫星影像、CartoDB、Esri、Stamen 或其他瓦片提供商。图层名称位于内置的 providers 列表中。

library(leaflet)

# Default OpenStreetMap
map1 <- leaflet() |> addTiles()

# CartoDB light theme (great for data overlay)
map2 <- leaflet() |>
  addProviderTiles(providers$CartoDB.Positron)

# Satellite imagery
map3 <- leaflet() |>
  addProviderTiles(providers$Esri.WorldImagery)

# Custom tile URL
custom <- leaflet() |>
  addTiles(
    urlTemplate = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
    attribution  = '(c) OpenStreetMap contributors'
  )

map2

使用 addMarkers 添加弹出窗口

addMarkers(lng, lat, popup) 会向地图添加图钉标记。popup 参数接受 HTML 字符串,因此您可以加入粗体文本、链接或图像。label 参数会在鼠标悬停时显示文本,无需点击。

library(leaflet)

cities <- data.frame(
  name = c('New York', 'Los Angeles', 'Chicago'),
  lon  = c(-74.006, -118.244, -87.629),
  lat  = c( 40.713,   34.052,  41.878),
  pop  = c(8336817,  3979576, 2693976)
)

leaflet(cities) |>
  addTiles() |>
  addMarkers(
    lng   = ~lon,
    lat   = ~lat,
    popup = ~paste0(
      '<b>', name, '</b><br>',
      'Population: ', format(pop, big.mark = ',')
    ),
    label = ~name
  )

addCircleMarkers

addCircleMarkers() 绘制大小固定为屏幕像素的圆(不同于会随缩放级别变化的 addCircles())。它们非常适合表示比例符号——将 radius 映射到某个数据变量。

library(leaflet)

cities <- data.frame(
  name = c('New York', 'Los Angeles', 'Chicago', 'Houston', 'Phoenix'),
  lon  = c(-74.006, -118.244, -87.629, -95.369, -112.074),
  lat  = c( 40.713,   34.052,  41.878,  29.760,   33.449),
  pop  = c(8336817,  3979576, 2693976, 2304580, 1608139)
)

leaflet(cities) |>
  addProviderTiles(providers$CartoDB.Positron) |>
  addCircleMarkers(
    lng    = ~lon,
    lat    = ~lat,
    radius = ~sqrt(pop / 50000),
    color  = 'steelblue',
    fill   = TRUE,
    fillOpacity = 0.6,
    popup  = ~paste0(name, ': ', format(pop, big.mark = ','))
  )

addPolygons:分级设色地图

addPolygons() 直接从 sf 对象绘制多边形几何图形。可以使用 colorNumeric() 或 colorBin() 调色板函数,将填充颜色映射到数据列。highlight 选项可以添加悬停效果。

library(leaflet)
library(sf)

nc <- st_transform(
  read_sf(system.file('shape/nc.shp', package = 'sf')), 4326
)

# Colour palette based on birth count
pal <- colorNumeric('YlOrRd', domain = nc$BIR74)

leaflet(nc) |>
  addProviderTiles(providers$CartoDB.Positron) |>
  addPolygons(
    fillColor   = ~pal(BIR74),
    fillOpacity = 0.7,
    color       = 'white',
    weight      = 1,
    popup       = ~paste0('<b>', NAME, '</b><br>Births 1974: ', BIR74),
    highlight   = highlightOptions(
      weight    = 3,
      color     = '#333',
      bringToFront = TRUE
    )
  ) |>
  addLegend('bottomright', pal = pal, values = ~BIR74, title = 'Births 1974')

setView 和 fitBounds

setView(lng, lat, zoom) 将地图中心设置在固定位置,并设定缩放级别。fitBounds(lng1, lat1, lng2, lat2) 会自动缩放地图,以适应地理边界框;当您事先不知道数据范围时,这一功能非常有用。

library(leaflet)
library(sf)

nc <- st_transform(
  read_sf(system.file('shape/nc.shp', package = 'sf')), 4326
)
bbox <- st_bbox(nc)

# fitBounds: auto-zoom to data extent
leaflet() |>
  addTiles() |>
  fitBounds(
    lng1 = bbox['xmin'], lat1 = bbox['ymin'],
    lng2 = bbox['xmax'], lat2 = bbox['ymax']
  ) |>
  addPolygons(
    data        = nc,
    fillColor   = 'lightblue',
    fillOpacity = 0.4,
    color       = 'steelblue',
    weight      = 1
  )

addLayersControl:切换图层

addLayersControl() 添加单选按钮或复选框控件,用于打开或关闭底图和叠加图层。对于互斥的瓦片图层,请使用 baseGroups;对于可以独立切换的数据图层,请使用 overlayGroups。

library(leaflet)
library(sf)

nc <- st_transform(
  read_sf(system.file('shape/nc.shp', package = 'sf')), 4326
)

high_birth  <- nc[nc$BIR74 > 3000, ]
low_birth   <- nc[nc$BIR74 <= 3000, ]

leaflet() |>
  addProviderTiles(providers$CartoDB.Positron, group = 'Light') |>
  addProviderTiles(providers$Esri.WorldImagery, group = 'Satellite') |>
  addPolygons(data = high_birth, color = 'red',   group = 'High Births (>3000)') |>
  addPolygons(data = low_birth,  color = 'blue',  group = 'Low Births (<=3000)') |>
  addLayersControl(
    baseGroups    = c('Light', 'Satellite'),
    overlayGroups = c('High Births (>3000)', 'Low Births (<=3000)'),
    options       = layersControlOptions(collapsed = FALSE)
  )

addPopups 和 addLegend

addPopups() 添加持久显示(始终可见)的弹出框。addLegend() 创建与调色板关联的地图图例。两者都支持 HTML 内容,并且可以通过 CSS 类进行全面自定义。

library(leaflet)

leaflet() |>
  addTiles() |>
  setView(-79.0, 35.5, zoom = 7) |>
  addPopups(
    lng     = -78.639,
    lat     =  35.779,
    popup   = '<b>Raleigh</b><br>State Capital of NC'
  ) |>
  addLegend(
    position = 'bottomleft',
    colors   = c('red', 'blue', 'green'),
    labels   = c('High', 'Medium', 'Low'),
    title    = 'Risk Level',
    opacity  = 0.8
  )

颜色调色板:colorNumeric 和 colorBin

colorNumeric()、colorBin()、colorQuantile() 和 colorFactor() 函数会创建调色板函数,将数据值映射为十六进制颜色。将结果传递给 fillColor,并将同一个调色板传递给 addLegend()。

library(leaflet)
library(sf)

nc <- st_transform(
  read_sf(system.file('shape/nc.shp', package = 'sf')), 4326
)

# Continuous palette
pal_num <- colorNumeric('Blues', domain = nc$BIR74)

# Binned palette (5 equal bins)
pal_bin <- colorBin('RdYlGn', domain = nc$BIR74, bins = 5)

# Quantile palette (equal number of features per class)
pal_qtl <- colorQuantile('YlOrRd', domain = nc$BIR74, n = 4)

# Use binned palette
leaflet(nc) |>
  addTiles() |>
  addPolygons(
    fillColor   = ~pal_bin(BIR74),
    fillOpacity = 0.7, weight = 1, color = 'white'
  ) |>
  addLegend('bottomright', pal = pal_bin, values = ~BIR74,
            title = 'Births 1974 (5 bins)')

leafletProxy:在 Shiny 中更新地图

leafletProxy('mapId') 可以在 Shiny 应用中更新已有的 leaflet 地图,而无需从头重新渲染整张地图。将它与 clearMarkers()、clearShapes() 或 addMarkers() 搭配使用,可以高效地响应用户输入。

library(shiny)
library(leaflet)

# Minimal Shiny app with leafletProxy
ui <- fluidPage(
  selectInput('colour', 'Marker colour:', choices = c('red', 'blue', 'green')),
  leafletOutput('map')
)

server <- function(input, output, session) {
  output$map <- renderLeaflet({
    leaflet() |> addTiles() |>
      setView(-79.0, 35.5, zoom = 7)
  })

  observeEvent(input$colour, {
    leafletProxy('map') |>
      clearMarkers() |>
      addCircleMarkers(
        lng   = -78.639, lat = 35.779,
        color = input$colour,
        label = paste('Raleigh -', input$colour)
      )
  })
}

# shinyApp(ui, server)  # uncomment to run

完整的交互式分级设色地图

下面是一个达到生产质量的分级设色地图示例,结合了所有关键功能:提供商瓦片、多边形填充、悬停高亮、动态弹出框、颜色图例和图层控件——全部代码不到 25 行。

library(leaflet)
library(sf)

nc <- st_transform(
  read_sf(system.file('shape/nc.shp', package = 'sf')), 4326
)
pal <- colorQuantile('YlOrRd', domain = nc$SID74, n = 5)

leaflet(nc) |>
  addProviderTiles(providers$CartoDB.Positron) |>
  addPolygons(
    fillColor   = ~pal(SID74),
    fillOpacity = 0.75,
    color       = 'white',
    weight      = 0.5,
    popup       = ~paste0('<b>', NAME, '</b><br>SIDS 1974: ', SID74),
    highlight   = highlightOptions(
      weight = 2, color = '#555', bringToFront = TRUE
    )
  ) |>
  addLegend(
    position = 'bottomright',
    pal = pal, values = ~SID74,
    title = 'SIDS Deaths 1974<br>(Quintiles)'
  ) |>
  addControl('<b>NC SIDS Data 1974</b>', position = 'topright')

快速检查

在 Shiny 应用中,当用户更改下拉菜单时,您希望更新现有 leaflet 地图上的标记位置,同时不重新渲染整张地图。应该使用哪个函数?

回顾:leaflet 包

要点:

  • leaflet() |> addTiles() 使用 OpenStreetMap 瓦片创建交互式地图
  • addProviderTiles(providers$) 切换到其他瓦片提供商
  • 点数据使用 addMarkers() / addCircleMarkers();同时使用 popup 和 label
  • 使用 addPolygons(fillColor = ~pal(col)) 创建分级设色地图
  • colorNumeric()、colorBin()、colorQuantile() 创建调色板函数
  • addLegend() 与调色板函数配合使用;addLayersControl() 用于切换图层
  • 使用 leafletProxy() 高效更新 Shiny 地图
  • fitBounds() 自动缩放到数据范围
library(leaflet)

# Three-line interactive map
leaflet() |>
  addProviderTiles(providers$CartoDB.Positron) |>
  addCircleMarkers(lng = c(-74, -118, -88), lat = c(41, 34, 42),
                   label = c('NYC', 'LA', 'Chicago'), color = 'steelblue')

常见问题解答

「使用 leaflet 创建交互式地图」课时是免费的吗?

是的 — 「使用 leaflet 创建交互式地图」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 R Academy 课程的其余内容,请升级到 CoddyKit PRO。 R Academy 课程共包含 4 节课。

「使用 leaflet 创建交互式地图」这节课中我会学到什么?

使用标记、弹出窗口和图块图层渲染交互式网络地图 你通过在浏览器中直接运行的动手代码来练习 R Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 R Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 R Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「使用 leaflet 创建交互式地图」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 R Academy 课中编写并运行代码吗?

能。每节 R Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 使用 sf 软件包处理简单要素
  2. 坐标参考系与投影
  3. 空间连接与空间操作
  4. 使用 leaflet 创建交互式地图
← 返回 R Academy