求助:使用R的tiler包为Leaflet仪表盘创建栅格瓦片失败
问题与解决方案
需求说明
制作flexdashboard仪表盘时,希望通过Leaflet加载本地栅格瓦片替代多边形图层以提升渲染速度。使用R的tiler包将多边形数据先栅格化再生成多缩放级别的瓦片,每组瓦片对应不同的SID79分组,但当前代码运行失败,期望效果为将下图中的多边形替换为瓦片图层:
原错误代码
--- title: "try" date: "`r Sys.Date()`" output: flexdashboard::flex_dashboard: orientation: rows vertical_layout: fill runtime: shiny --- ```{r setup, include = FALSE} knitr::opts_chunk$set(echo=FALSE) library(flexdashboard) library(shiny) library(tidyverse) library(sf) library(leaflet) library(stars) library(tiler) pdf(NULL) nc <- st_read(system.file("shape/nc.shp", package="sf")) %>% st_transform(4326) subset <- nc %>% filter(SID74 <=5) # map splitField <- "SID79" years <- unique(subset[[splitField]]) subset$SID74 <- as.character(subset$SID74) for (i in 1:length(years)) { tmp <- subset[subset[[splitField]] == years[i], ] assign(paste0("year", i), tmp) }
Map
Row
Map
colour6 <- tibble( numbers = c("0", "1", "2", "3", "4","5"), Color = c('#FFFF33', '#00CC99', '#006633' , '#99CC99', '#6699CC','#CC9900')) m1 <- leaflet() %>% setView(lng = -79.5, lat = 36,zoom =7) %>% addTiles(group = "OSM (default)") for (i in 1:length(years)) { dat <- get(paste0("year",i)) dat_col <- merge( x =dat, y =colour6, by.x ="SID74", by.y="numbers") ras <- st_rasterize(dat_col[,"numbers"], dx= 100, dy = 100) ras4326 <- st_warp(ras, crs = st_crs(4326)) # create subfolders in existing path dir.create(file.path("./", i), showWarnings = FALSE) tile_dir <- file.path(paste0("./",i)) tiles <- tile(ras4326, tile_dir, "0-3", col = colour6$Color) m1 <- m1 %>% addTiles(tiles, group = paste0(i), options = tileOptions(opacity = 0.8)) } m1 <- m1 %>% addLayersControl( baseGroups = c("OSM"), options = layersControlOptions(collapsed = FALSE), overlayGroups = unique(years)) %>% addLegend(colors = colour6$Color, labels = colour6$numbers) renderLeaflet({ m1 })
## 问题分析 1. **栅格分辨率不合理**:`st_rasterize`中`dx=100, dy=100`对应经纬度CRS(4326)下的100度,分辨率过大导致栅格无有效数据 2. **瓦片路径错误**:`addTiles`需要的是瓦片的访问路径,`tiler::tile`返回的是本地目录,需转换为相对URL格式 3. **栅格化字段错误**:栅格化时应使用颜色对应的数值字段,而非合并后的`numbers`字段 4. **变量管理低效**:用`assign`生成多个变量不如用列表存储分组数据更简洁可靠 ## 修正后的完整代码 ```yaml --- title: "Tile-based Leaflet Dashboard" date: "`r Sys.Date()`" output: flexdashboard::flex_dashboard: orientation: rows vertical_layout: fill runtime: shiny --- ```{r setup, include = FALSE} knitr::opts_chunk$set(echo=FALSE) library(flexdashboard) library(shiny) library(tidyverse) library(sf) library(leaflet) library(stars) library(tiler) # 避免PDF设备冲突 pdf(NULL) # 加载并预处理数据 nc <- st_read(system.file("shape/nc.shp", package="sf")) %>% st_transform(4326) subset <- nc %>% filter(SID74 <=5) splitField <- "SID79" years <- unique(subset[[splitField]]) subset$SID74 <- as.character(subset$SID74) # 用列表存储分组数据,替代assign year_list <- split(subset, subset[[splitField]]) # 颜色映射表 colour6 <- tibble( numbers = c("0", "1", "2", "3", "4","5"), Color = c('#FFFF33', '#00CC99', '#006633' , '#99CC99', '#6699CC','#CC9900') )
Map
Row
Map
renderLeaflet({ m <- leaflet() %>% setView(lng = -79.5, lat = 36, zoom =7) %>% addTiles(group = "OSM (default)") # 遍历每个年份分组生成瓦片并添加图层 for (i in seq_along(year_list)) { dat <- year_list[[i]] current_year <- names(year_list)[i] # 合并颜色映射 dat_col <- merge(dat, colour6, by.x ="SID74", by.y="numbers") # 栅格化:使用合理的经纬度分辨率(0.01度,约1公里) # 基于SID74的数值栅格化,后续用颜色映射匹配 ras <- st_rasterize(dat_col["SID74"], dx = 0.01, dy = 0.01) # 创建瓦片存储目录 tile_dir <- file.path("tiles", current_year) dir.create(tile_dir, recursive = TRUE, showWarnings = FALSE) # 生成瓦片:指定颜色映射,缩放级别设为7-10(适配初始视图) tile(ras, tile_dir, zoom = "7-10", col = colour6$Color, breaks = as.integer(colour6$numbers)) # 本地瓦片的URL路径格式:用相对路径指向瓦片目录 tile_url <- file.path(".", tile_dir, "{z}/{x}/{y}.png") # 添加瓦片图层 m <- m %>% addTiles(urlTemplate = tile_url, group = current_year, options = tileOptions(opacity = 0.8, tms = FALSE)) } # 添加图层控制和图例 m %>% addLayersControl( baseGroups = c("OSM (default)"), overlayGroups = names(year_list), options = layersControlOptions(collapsed = FALSE) ) %>% addLegend(colors = colour6$Color, labels = colour6$numbers) })
## 关键修正点 1. **栅格分辨率调整**:将`dx`和`dy`设为`0.01`(经纬度下的0.01度,适配地图缩放级别) 2. **瓦片路径处理**:生成相对URL格式的瓦片路径,确保Leaflet能正确加载本地瓦片 3. **颜色映射匹配**:在`tile`函数中通过`breaks`参数将数值与颜色对应 4. **数据结构优化**:用`split`生成列表存储分组数据,替代`assign`提升代码可读性 5. **缩放级别适配**:将瓦片缩放级别设为`7-10`,匹配初始地图视图的缩放范围 内容的提问来源于stack exchange,提问作者jaykay
相关产品推荐
相关产品推荐

