如何用R的sf包创建带放大区域及连接红区的欧洲地图?
在sf地图中添加主图与放大区域的连接阴影
自动生成连接阴影的实现方法
核心思路是通过坐标转换将主图的地理坐标放大框,与ggdraw中子图的边框坐标统一到归一化(0-1)的画布坐标系,再构建连接两者的闭合多边形,最后填充半透明红色。
以下是完整代码示例:
library(sf) library(ggplot2) library(cowplot) library(rnaturalearth) # 1. 获取欧洲地图数据 europe <- ne_countries(continent = "europe", returnclass = "sf") # 2. 定义需要放大的区域(示例为意大利北部,可自行调整经纬度) zoom_bbox <- st_bbox(c(xmin = 8, xmax = 13, ymin = 44, ymax = 47), crs = st_crs(europe)) zoom_area <- st_as_sfc(zoom_bbox) # 3. 绘制主地图,标记放大框 main_plot <- ggplot() + geom_sf(data = europe, fill = "#f0f0f0", color = "gray50") + geom_sf(data = zoom_area, fill = NA, color = "red", linewidth = 1) + theme_minimal() + theme(axis.text = element_blank(), axis.title = element_blank()) # 4. 绘制放大后的子图 zoom_plot <- ggplot() + geom_sf(data = europe %>% st_crop(zoom_bbox), fill = "#f0f0f0", color = "gray50") + theme_minimal() + theme(axis.text = element_blank(), axis.title = element_blank()) # 5. 构建连接阴影的多边形 # 提取主图放大框的顶点坐标 main_box_points <- st_coordinates(zoom_area)[1:4, 1:2] # 定义子图在画布中的位置(右下角,占比30%宽高) subplot_x <- 0.7 subplot_y <- 0.1 subplot_width <- 0.3 subplot_height <- 0.3 # 生成子图边框的归一化坐标(画布范围0-1) sub_box_points <- matrix( c(subplot_x, subplot_y, subplot_x + subplot_width, subplot_y, subplot_x + subplot_width, subplot_y + subplot_height, subplot_x, subplot_y + subplot_height), ncol = 2, byrow = TRUE ) # 将主图的地理坐标转换为画布归一化坐标 main_x_range <- ggplot_build(main_plot)$layout$panel_params[[1]]$x.range main_y_range <- ggplot_build(main_plot)$layout$panel_params[[1]]$y.range main_box_norm <- cbind( (main_box_points[,1] - main_x_range[1]) / diff(main_x_range), (main_box_points[,2] - main_y_range[1]) / diff(main_y_range) ) # 按顺序拼接连接点(确保多边形闭合且形状合理) connect_points <- rbind( main_box_norm[3, ], # 主框右下角 main_box_norm[2, ], # 主框右上角 sub_box_points[3, ], # 子框右上角 sub_box_points[4, ], # 子框左上角 main_box_norm[3, ] # 回到起点闭合 ) connect_poly <- st_polygon(list(connect_points)) %>% st_sfc(crs = NA) # 6. 组合所有元素 final_plot <- ggdraw() + draw_plot(main_plot) + draw_plot(zoom_plot, x = subplot_x, y = subplot_y, width = subplot_width, height = subplot_height) + draw_geom(connect_poly, fill = "red", alpha = 0.2, color = NA) print(final_plot)
替代方案
如果自动生成的坐标转换过于繁琐,可采用手动绘制多边形的简化方式:
- 通过
ggdraw()的annotate("polygon")函数,直接输入归一化坐标点来绘制连接阴影,适合固定布局的场景。 - 示例代码片段:
final_plot <- ggdraw() + draw_plot(main_plot) + draw_plot(zoom_plot, x = 0.7, y = 0.1, width = 0.3, height = 0.3) + annotate("polygon", x = c(0.6, 0.7, 1, 0.9, 0.6), y = c(0.3, 0.1, 0.1, 0.4, 0.3), fill = "red", alpha = 0.2)
关键注意事项
- 坐标转换时需确保主图的地理坐标与画布归一化坐标映射正确,否则连接区域会错位。
- 调整连接点的顺序可改变阴影的形状,按需选择主框与子框的连接边角。
- 通过
alpha参数控制阴影透明度,避免遮挡地图内容。
内容的提问来源于stack exchange,提问作者J. Doe
相关产品推荐
相关产品推荐

