Leaflet 与高德继续碰撞火花!

简介: 我们对 leaflet 包做了一期简单的入门教程:空间地理数据可视化之 leaflet 包及其拓展。之后,又将高德和该包相结合,介绍了前期需要准备的工作,见:Leaflet 与高德合并会擦出怎么样的火花?。这一期就到了绘制地图环节,下面将分享三类数据的绘制教程。

前言


我们对 leaflet 包做了一期简单的入门教程:空间地理数据可视化之 leaflet 包及其拓展。之后,又将高德和该包相结合,介绍了前期需要准备的工作,见:Leaflet 与高德合并会擦出怎么样的火花?。这一期就到了绘制地图环节,下面将分享三类数据的绘制教程。


本文框架


这篇推文讲的是第三节内容


3. 绘制地图


3.1 散点地图绘制

  1. 将高德地图替换 leaflet 自带的底图

由于 leaflet 自带的底图不是很合规,所以我们使用高德地图进行替换。

library(leaflet)
geo_map <- leaflet(width = '100%') %>% 
  addTiles(
    urlTemplate = 'http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
    layerId = tileOptions(minZoom = 3, maxZoom = 17),
    attribution = NULL
  )
  1. 在地图上增加标记

使用addMarkers()geo_map上增加散点图。

geo_map %>% 
  addMarkers(
    data = datafile,  ## 存放有坐标的文件
    lat = ~lat,       ## 变量纬度(latitude)所在列
    lng = ~lng,       ## 变量经度(longitude)所在列
    label = ~address  ## 变量标签所在列(这里设置了详细的地址作为标签)
    )

  1. 批量下载 api 地址

高德地图地理编码的 api 每天可以查询 30 万次,所以可以将上述查询过程写成一个 function 来进行批量查询。代码如下,代码中的注释已做详细解释。

## 加载packages
library(dplyr)
library(tidyr)
library(leaflet)
## 设置文件
datafile <- data.frame(
  id = 1:9,
  address = c(
    "北京市东城区天安门广场人民英雄纪念碑",
    "上海市浦东新区东方明珠广播电视塔",
    "台湾省台北市南京东路台北体育馆",
    "海南省海口市海口站(出站口)",
    "香港特别行政区湾仔区岛湾仔博览道1号会议展览中心香港回归祖国纪念碑",
    "澳门特别行政区花王堂区澳门博物馆大炮台(北入口)",
    "西藏拉萨市城关区布达拉宫广场西藏和平解放纪念碑",
    "新疆克拉玛依市平南八路克拉玛依北站",
    "黑龙江省哈尔滨市道里区斯大林街20号哈尔滨市人民防洪胜利纪念塔"
  )
)
## 自定义function
gaodemap <- function(x){
  address <- stringr::str_replace_all(datafile$address[x], "[^[:alnum:]]", "") ## 去除特殊字符,部分特殊字符会导致查询失败,所以在最开始直接去除
  url <- paste0(
    'https://restapi.amap.com/v3/geocode/geo?',
    '&key=', key, ## key
    '&address=', address, ## 详细地址
    '&output=', 'JSON'
  )
  temp_geo <- fromJSON(paste(readLines(url,warn = F, encoding = 'UTF-8'), collapse = ""))
  status <- temp_geo$status ## 判断查询是否成功
  if (status == 1 & length(temp_geo$geocodes) != 0){ ## 有时候成功了但是没有收到数据,所以用了一个“且”进行判定
    temp <- paste(datafile$address[x], temp_geo$geocodes$location, sep = ",")
  } else {
    temp <- paste(datafile$address[x], 'NULL,NULL', sep = ",")
  }
  return(temp)
}
## 地理编码
df <- data.frame(
  geo = sapply(datafile$id, gaodemap, simplify = T)
) %>% 
  separate(col = geo, into = c('address', 'lng', 'lat'), sep = ',') ## 分割function的结果
df$lng <- as.numeric(df$lng)
df$lat <- as.numeric(df$lat)
df
##                                                             address       lng
## 1                              北京市东城区天安门广场人民英雄纪念碑 116.39768
## 2                                  上海市浦东新区东方明珠广播电视塔 121.50003
## 3                                    台湾省台北市南京东路台北体育馆 121.54067
## 4                                        海南省海口市海口站(出站口) 110.16203
## 5 香港特别行政区湾仔区岛湾仔博览道1号会议展览中心香港回归祖国纪念碑 114.17738
## 6                    澳门特别行政区花王堂区澳门博物馆大炮台(北入口) 113.54620
## 7                    西藏拉萨市城关区布达拉宫广场西藏和平解放纪念碑  91.11885
## 8                                新疆克拉玛依市平南八路克拉玛依北站  85.08215
## 9      黑龙江省哈尔滨市道里区斯大林街20号哈尔滨市人民防洪胜利纪念塔 126.61724
##        lat
## 1 39.90462
## 2 31.23925
## 3 25.05213
## 4 20.02724
## 5 22.28094
## 6 22.19486
## 7 29.65127
## 8 45.56794
## 9 45.78065
  1. 绘图

这里我们将上面获得的df数据进行绘制,可以得到以下图形

geo_map <- leaflet(width = '100%') %>% 
  addTiles(
    urlTemplate = 'http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
    layerId = tileOptions(minZoom = 3, maxZoom = 17),
    attribution = NULL
  )
geo_map %>% 
  addMarkers(
    data = df,
    lat = ~lat, 
    lng = ~lng, 
    label = ~address
    )

补充:如果数据量较大,可以考虑使用 parallel 和 foreach 等来实现并行访问和解析 api,因为 R 语言默认是单核运行的,所以会出现**“一核有难,多核围观”**的情形,使用并行运算可以使电脑发挥出多核的优势,提升数据处理速度。

您可能会发现高德限制每秒 api 访问量是 200 次,多核并行会超限,就我的经验而言每次访问和解析大概需要 0.1 秒,16 线程并行查询 api,一秒钟也就160次,更何况还存在网络波动,所以基本上不用担心超限问题。


3.2 路径地图绘制

  1. 按照画线图的经验,平面直角坐标系中的一条线的位置由两个点决定,而两个点位置由它们分别的坐标 (X, Y)  决定,同理路径地图上的线由起点和终点决定,起点和终点由它们对应的经纬度决定,这样子我们就可以知道绘制路径地图的数据至少需要 4 个值,分别表示起点的经纬度和终点的经纬度。
  2. 知道了绘图需要的基本数据,后面的就简单了,只要分别查询两个点的经纬度把他们合并到一个表就好了,这里就不赘述了。有数据的朋友也可以直接把数据整理下就行,下面的例子使用上面绘制散点地图的数据。
  3. 先把数据整理下,假如说希望画从北京到另外 8 个点的直线,我只要在上表中新增一个点作为线段起点就好
df_line <- df %>%  
  mutate(              
    lat_start = lat[1], ## 新增起点纬度
    lng_start = lng[1]  ## 新增起点经度
  )
df_line
##                                                             address       lng
## 1                       北京市东城区天安门广场人民英雄纪念碑 116.39768
## 2                                  上海市浦东新区东方明珠广播电视塔 121.50003
## 3                                    台湾省台北市南京东路台北体育馆 121.54067
## 4                                        海南省海口市海口站(出站口) 110.16203
## 5 香港特别行政区湾仔区岛湾仔博览道1号会议展览中心香港回归祖国纪念碑 114.17738
## 6                    澳门特别行政区花王堂区澳门博物馆大炮台(北入口) 113.54620
## 7                    西藏拉萨市城关区布达拉宫广场西藏和平解放纪念碑  91.11885
## 8                                新疆克拉玛依市平南八路克拉玛依北站  85.08215
## 9      黑龙江省哈尔滨市道里区斯大林街20号哈尔滨市人民防洪胜利纪念塔 126.61724
##        lat lat_start lng_start
## 1 39.90462  39.90462  116.3977
## 2 31.23925  39.90462  116.3977
## 3 25.05213  39.90462  116.3977
## 4 20.02724  39.90462  116.3977
## 5 22.28094  39.90462  116.3977
## 6 22.19486  39.90462  116.3977
## 7 29.65127  39.90462  116.3977
## 8 45.56794  39.90462  116.3977
## 9 45.78065  39.90462  116.3977
  1. 分组合并下数据
df_line <- data.frame(
  group = rownames(df_line),
  lat = c(df_line$lat, df_line$lat_start),
  lng = c(df_line$lng, df_line$lng_start)
) %>% 
  group_by(group) %>% 
  arrange(.by_group = TRUE)
df_line
## # A tibble: 18 x 3
## # Groups:   group [9]
##    group   lat   lng
##    <chr> <dbl> <dbl>
##  1 1      39.9 116. 
##  2 1      39.9 116. 
##  3 2      31.2 122. 
##  4 2      39.9 116. 
##  5 3      25.1 122. 
##  6 3      39.9 116. 
##  7 4      20.0 110. 
##  8 4      39.9 116. 
##  9 5      22.3 114. 
## 10 5      39.9 116. 
## 11 6      22.2 114. 
## 12 6      39.9 116. 
## 13 7      29.7  91.1
## 14 7      39.9 116. 
## 15 8      45.6  85.1
## 16 8      39.9 116. 
## 17 9      45.8 127. 
## 18 9      39.9 116.
  1. 绘图
geo_map <- leaflet(width = '100%') %>% 
  addTiles(
    urlTemplate = 'http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
    layerId = tileOptions(minZoom = 3, maxZoom = 17),
    attribution = NULL
  )
geo_map %>% 
  addPolylines(
    data = df_line,  ## 存放有坐标文件 
    lng = ~lng,  ## 变量经度(longitude)所在列
    lat = ~lat,  ## 变量纬度(latitude)所在列
    group = ~group,  ## 线条分组
    weight = 1,  ## 线条粗细
    color = "red" ##线条颜色
  )

image.gifimage.gif


3.3 导航路径图

这个是看高德地图的时候无意中发现的,高德还提供 api 来查询导航路径,详细可见:官方说明文档[1]

  1. 通过地理编码获得起点和终点的经纬度,方法同上不再赘述了。
address1 <- '福建省厦门市厦门高崎国际机场' ## 起点详细地址
address2 <- '福建省厦门市厦门大学思明校区' ## 终点详细地址
url1 <- paste0(  ## 查询起点的url
  "https://restapi.amap.com/v3/geocode/geo?address=", address1,
  "&output=JSON&key=", key
) 
url2 <- paste0(  ## 查询终点的url
  "https://restapi.amap.com/v3/geocode/geo?address=", address2,
  "&output=JSON&key=", key
)
address1 <- fromJSON(paste(readLines(url1,warn = F, encoding = 'UTF-8'), collapse = "")) ## 起点坐标
address2 <- fromJSON(paste(readLines(url2,warn = F, encoding = 'UTF-8'), collapse = "")) ## 终点坐标
print(address1$geocodes) 
##                formatted_address country province citycode   city district
## 1 福建省厦门市湖里区高崎国际机场    中国   福建省     0592 厦门市   湖里区
##   township neighborhood.name neighborhood.type building.name building.type
## 1     NULL              NULL              NULL          NULL          NULL
##   adcode street number             location  level
## 1 350206   NULL   NULL 118.137053,24.539473 兴趣点
print(address2$geocodes)
##                    formatted_address country province citycode   city district
## 1 福建省厦门市思明区厦门大学思明校区    中国   福建省     0592 厦门市   思明区
##   township neighborhood.name neighborhood.type building.name building.type
## 1     NULL              NULL              NULL          NULL          NULL
##   adcode street number             location  level
## 1 350203   NULL   NULL 118.093470,24.437154 兴趣点
  1. 按照说明文档要求,生成url。
url <- paste0(
  "https://restapi.amap.com/v5/direction/bicycling?", 
  ## 使用骑行路线的api,如果是步行或者驾车,需要按照说明文档修改即可
  "&output=", "JSON",
  "&key=", key,
  '&origin=', address1$geocodes$location, ## 设置起点经纬度
  '&destination=', address2$geocodes$location,  ## 设置终点经纬度
  '&show_fields=', 'polyline' ## 设置显示坐标点
)
## 查询api
address <- fromJSON(paste(readLines(url,warn = F, encoding = 'UTF-8'), collapse = ""))
  1. 导航路径的经纬度信息分成不同段的储存在“route-paths-steps-polyline”中。
head(address$route$paths$steps[[1]]$polyline)
## [1] "118.13766;....
  1. 整理数据
## 经纬度分割开
datafile <- lapply(1:length(address[["route"]][["paths"]][["steps"]][[1]][["polyline"]]), function(x){
    df <- strsplit(address[["route"]][["paths"]][["steps"]][[1]][["polyline"]][[x]], ";")
    return(df)
})
## 转化成表格
df <- data.frame(
  id = matrix(unlist(datafile))
) %>% 
  separate(id, c('lng', 'lat'), ",") %>% 
  mutate_if(is.character, as.numeric)
  1. 绘制地图
leaflet(df, width = '100%') %>% 
  addTiles(
    urlTemplate = 'http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
    layerId = tileOptions(minZoom = 3, maxZoom = 17),
    attribution = NULL
  ) %>% 
  addPolylines(  ## 绘制路线
    lat = ~lat, 
    lng = ~lng
    ) %>% 
  addMarkers(  ## 绘制起点所在点
    lat = ~lat[1], 
    lng = ~lng[1], 
    label = paste0('起点:', address1$geocodes$formatted_address)
    )%>% 
  addMarkers( ## 绘制终点所在点
    lat = ~lat[nrow(df)], 
    lng = ~lng[nrow(df)], 
    label = paste0('终点:', address2$geocodes$formatted_address)
    )

目录
相关文章
|
1月前
|
小程序 搜索推荐 前端开发
小剧场短剧影视小程序开发
小剧场短剧影视小程序旨在为用户提供一个便捷、互动的平台,让用户能够随时随地观看、分享和评论各类小剧场短剧。通过小程序,用户可以浏览热门短剧、搜索感兴趣的内容、参与社区互动,以及享受个性化的推荐服务。
|
编解码 算法 前端开发
《移动端的真实感渲染-慎思》演讲视频 + 文字版
《移动端的真实感渲染-慎思》演讲视频 + 文字版
158 0
|
传感器 前端开发 vr&ar
三种前端实现VR全景看房的方案!说不定哪天就用得上!(上)
事情是这样的,前几天我接到一个外包工头的新需求,某品牌要搭建一个在线VR展厅,用户可以在手机上通过陀螺仪或者拖动来360度全景参观展厅,这个VR展厅里会有一些信息点,点击之后可以呈现更多信息(视频,图文等)... 我第一反应是用3D引擎,因为我不久前刚用three.js做过一个BMW的在线展厅,基本把three.js摸熟了。
557 0
三种前端实现VR全景看房的方案!说不定哪天就用得上!(上)
|
存储 安全 定位技术
高德地图开发汇总
高德地图主要分为地图开发、导航开发、定位开发、室内地图、室内定位。总结一下在项目中用到的地图开发。 Demo地址 DEMO比较简单,集成了3d地图和搜索sdk,可以根据自己的需求添加功能。
1594 0
|
传感器 移动开发 数据可视化
三种前端实现VR全景看房的方案!说不定哪天就用得上! (下)
事情是这样的,前几天我接到一个外包工头的新需求,某品牌要搭建一个在线VR展厅,用户可以在手机上通过陀螺仪或者拖动来360度全景参观展厅,这个VR展厅里会有一些信息点,点击之后可以呈现更多信息(视频,图文等)... 我第一反应是用3D引擎,因为我不久前刚用three.js做过一个BMW的在线展厅,基本把three.js摸熟了。
1060 0
三种前端实现VR全景看房的方案!说不定哪天就用得上! (下)
|
机器学习/深度学习 人工智能 编解码
|
监控 安全 前端开发
闲鱼把各种玩法做成了一个平台:哆啦A梦
哆啦A梦的口袋里,都有哪些好玩的?
7276 0
闲鱼把各种玩法做成了一个平台:哆啦A梦
|
算法 自动驾驶 前端开发
阿里巴巴高德地图首席科学家任小枫:高精算法推动高精地图落地
阿里巴巴高德地图首席科学家任小枫分享的话题是《高精算法推动高精地图落地》。任小枫从算法出发,介绍了高精地图制作和落地的挑战,以及高德如何打磨和突破关键技术,把高精地图做到业界领先。
阿里巴巴高德地图首席科学家任小枫:高精算法推动高精地图落地
|
存储 Web App开发 移动开发
我在优酷OTT端做自动化制图 | 《优酷OTT互联网大屏前端技术实践》第五章
谈到自动化制图,主要有两种模式: 一是自动化模式:依赖于服务化能力包装,将核心制图能力进行抽取,任何三方通过直接调用服务能力即可完成图片的合成,此种模式完全自动化,无需任何人工干预即可制作出符合指定条件的业务图片; 二是半自动化模式:主要依赖于业务共性的提取与升华,将繁琐的重复的业务流程通过统一的范式来解决,或多或少的需要人工干预。人工干预一方面需要人力投入,另一方面意味着可以发挥人的主观创造性。成品图除了满足指定的共性外,也可以保证输出个性,这种个性与共性并存的方式不失为一种好的折中。
749 0
我在优酷OTT端做自动化制图 | 《优酷OTT互联网大屏前端技术实践》第五章
|
设计模式 缓存 移动开发
高德智慧景区随身听播放器框架设计与实现
我们开发选型并没有采用传统的TTS技术(由文本内容生成机器语音),而是采用了更加通用音频格式(比如mp3),作为讲解的音频输入源,方便讲解者进行二次创作。本文将简单回顾高德智慧景区随身听播放器的框架设计与实现。
高德智慧景区随身听播放器框架设计与实现
下一篇
无影云桌面