Windows下geom_sf填充失效:coord_sf设xlim/ylim时av包动画方案
Windows环境下ggplot2
coord_sf 填充失效的动画场景适配 已知问题说明
- 故障表现:Windows系统中,使用
coord_sf()手动指定xlim、ylim坐标范围时,geom_sf()图层的填充效果无法正常渲染 - 原有方案局限:目前公开的临时解决方式为将单帧绘图结果导出为PNG文件,该流程无法适配
av包的动画生成需求——av包需要直接在内存绘图设备上连续捕获数百帧图像拼接为视频,不支持逐帧落地存储、再重新读取的中转流程 - 常见应用场景:逐帧映射随时间变化的空间要素(如飓风移动轨迹),在通过坐标范围裁剪视图时会出现填充层异常消失的问题
可复现问题代码
library(tidyverse) library(sf) library(av) # 读取示例空间数据 tracts <- read_sf("https://opendata.arcgis.com/datasets/230f9d23f6874be983901876cd600c4e_0.geojson") %>% select( geometry, ALAND10, GEOID10 ) set.seed(264) v1 <- runif(1:dim(tracts)[1], .7, 1.25) tracts2 <- cbind(tracts, v1) # 构造两期时间维度的示例数据 tracts_2017 <- tracts2 %>% mutate(season=2017) tracts_2018 <- tracts2 %>% mutate( season=2018, ALAND10 = ALAND10*v1 ) tracts3 <- rbind(tracts_2017, tracts_2018) # 构造带coord_sf坐标裁剪的绘图帧(会触发填充失效bug) makeplot1 <- function(){ datalist <- split(tracts3, tracts3$season) mapply(function(data){ p1 <- ggplot() + geom_sf( data = data, aes(fill = ALAND10) ) + geom_sf( data = data %>% st_union(), fill = alpha("red", 0.4), color = alpha("red", 0.4) ) + coord_sf( ylim = c(43.04, 43.07), xlim = c(-76.14,-76.10), clip = "on", expand = F ) print(p1) }, datalist) } # 构造不带coord_sf坐标裁剪的绘图帧(渲染正常) makeplot2 <- function(){ datalist <- split(tracts3, tracts3$season) mapply(function(data){ p2 <- ggplot() + geom_sf( data = data, aes(fill = ALAND10) ) + geom_sf( data = data %>% st_union(), fill = alpha("red", 0.4), color = alpha("red", 0.4) ) print(p2) }, datalist) } # 生成动画测试 video_file1 <- file.path(tempdir(), 'Tracts1.mp4') av::av_capture_graphics(makeplot1(), video_file1, vfilter='framerate=fps=10') utils::browseURL(video_file1) video_file2 <- file.path(tempdir(), 'Tracts2.mp4') av::av_capture_graphics(makeplot2(), video_file2, vfilter='framerate=fps=10') utils::browseURL(video_file2)
适配方案(满足av包无PNG中转的动画生成要求)
- 数据层预裁剪方案
- 操作:在传入
geom_sf()前,使用st_crop()函数对sf对象按照目标x、y坐标范围提前裁剪;绘图时不再在coord_sf()中手动指定xlim/ylim参数,保留默认坐标范围设置 - 原理:提前从数据层面裁掉超出目标范围的几何要素,绕过Windows系统下
coord_sf内置裁剪逻辑引发的填充渲染bug;全程绘图流程在内存中完成,无中间PNG文件生成,可直接被av::av_capture_graphics()捕获
- 操作:在传入
- 设备切换方案
- 操作:在调用
av::av_capture_graphics()时指定device = ragg::agg_capture,替换Windows系统默认的GDI绘图设备 - 原理:
ragg设备采用独立的矢量渲染逻辑,不受Windows系统GDI渲染缺陷的影响,可正常渲染带坐标裁剪的sf填充层,适配内存中直接捕获帧的动画生成流程
- 操作:在调用
内容的提问来源于stack exchange,提问作者k6adams
相关产品推荐
相关产品推荐

