如何在东海岸地图上用geom_curve创建按月份渐变的弯箭头并添加环形箭头组?
解决方案
实现渐变弯箭头与环形箭头组
以下是满足需求的完整代码,包含两种实现渐变箭头的方式(一种依赖ggforce包简化操作,另一种纯基础包实现):
方法1:使用ggforce快速实现渐变弯箭头
ggforce::geom_link支持单条曲线的颜色沿路径渐变,代码更简洁:
require(sf); require(maps); require(ggplot2); require(ggforce) # 加载并筛选东海岸州地图数据 usmap <- st_as_sf(map("state", plot = F, fill = TRUE)) seaboard <- c('alabama', 'connecticut', 'georgia', 'maryland', 'mississippi', 'new jersey','new york', 'pennsylvania', 'south carolina', 'florida', 'north carolina', 'delaware','rhode island', 'massachusetts', 'virginia') monseq <- c('September','October','November','December') # 定义弯箭头的起点和终点 arrow_start <- data.frame(x = -75, y = 42.5) arrow_end <- data.frame(x = -85, y = 30.5) # 创建环形箭头组数据:三个顺时针首尾相连的弧形箭头 ring_center <- data.frame(x = -84.5, y = 31) # 箭头头部上方的环形中心 ring_radius <- 0.5 angles <- seq(0, 2*pi, length.out = 4)[-4] # 三个箭头的起始角度(间隔120度) ring_data <- data.frame( x = ring_center$x + ring_radius*cos(angles), y = ring_center$y + ring_radius*sin(angles), xend = ring_center$x + ring_radius*cos(angles + 2*pi/3), yend = ring_center$y + ring_radius*sin(angles + 2*pi/3) ) # 绘图 ggplot() + # 绘制东海岸州地图 geom_sf(data = usmap[usmap$ID %in% seaboard,], fill = "lightgrey") + # 绘制颜色渐变的弯箭头 geom_link( data = data.frame(x = arrow_start$x, y = arrow_start$y, xend = arrow_end$x, yend = arrow_end$y), aes(x = x, y = y, xend = xend, yend = yend, color = stat(index)), size = 3, curvature = -0.2, lineend = "round", arrow = arrow(length = unit(0.3, "cm")) ) + # 配置颜色渐变,对应月份标签 scale_color_gradient( low = "red", high = "blue", breaks = seq(1,4), labels = monseq, name = "Month" ) + # 绘制环形箭头组 geom_curve( data = ring_data, aes(x = x, y = y, xend = xend, yend = yend), curvature = 0.5, # 曲率设置让曲线贴合环形 color = "black", arrow = arrow(length = unit(0.2, "cm"), type = "closed") ) + theme_bw() + coord_sf(xlim = c(-88, -67), ylim = c(28, 45)) # 聚焦东海岸区域
方法2:纯基础包实现渐变弯箭头
如果不想额外安装ggforce,可以手动拆分弯箭头为多个渐变线段:
require(sf); require(maps); require(ggplot2) usmap <- st_as_sf(map("state", plot = F, fill = TRUE)) seaboard <- c('alabama', 'connecticut', 'georgia', 'maryland', 'mississippi', 'new jersey','new york', 'pennsylvania', 'south carolina', 'florida', 'north carolina', 'delaware','rhode island', 'massachusetts', 'virginia') monseq <- c('September','October','November','December') n_segments <- 100 # 拆分的渐变段数量 # 定义弯箭头参数 start_x <- -75; start_y <- 42.5 end_x <- -85; end_y <- 30.5 curvature <- -0.2 # 计算弯曲线上的所有点(模拟geom_curve的曲线逻辑) t <- seq(0, 1, length.out = n_segments) x <- start_x + t*(end_x - start_x) + curvature*(start_y - end_y)*(t - t^2) y <- start_y + t*(end_y - start_y) + curvature*(end_x - start_x)*(t - t^2) # 生成分段渐变的线段数据 arrow_segments <- data.frame( x = x[-n_segments], y = y[-n_segments], xend = x[-1], yend = y[-1], color_val = seq(1, 4, length.out = n_segments - 1) ) # 环形箭头组数据 ring_center <- data.frame(x = -84.5, y = 31) ring_radius <- 0.5 angles <- seq(0, 2*pi, length.out = 4)[-4] ring_data <- data.frame( x = ring_center$x + ring_radius*cos(angles), y = ring_center$y + ring_radius*sin(angles), xend = ring_center$x + ring_radius*cos(angles + 2*pi/3), yend = ring_center$y + ring_radius*sin(angles + 2*pi/3) ) # 绘图 ggplot() + geom_sf(data = usmap[usmap$ID %in% seaboard,], fill = "lightgrey") + # 绘制分段渐变的线段 geom_segment( data = arrow_segments, aes(x = x, y = y, xend = xend, yend = yend, color = color_val), size = 3, lineend = "round" ) + # 单独绘制带箭头的最后一段(对应12月的蓝色) geom_curve( data = data.frame(x = x[n_segments-1], y = y[n_segments-1], xend = end_x, yend = end_y), aes(x = x, y = y, xend = xend, yend = yend), color = "blue", size = 3, curvature = curvature, lineend = "round", arrow = arrow(length = unit(0.3, "cm")) ) + scale_color_gradient( low = "red", high = "blue", breaks = seq(1,4), labels = monseq, name = "Month" ) + # 绘制环形箭头组 geom_curve( data = ring_data, aes(x = x, y = y, xend = xend, yend = yend), curvature = 0.5, color = "black", arrow = arrow(length = unit(0.2, "cm")) ) + theme_bw() + coord_sf(xlim = c(-88, -67), ylim = c(28, 45))
关键说明
- 渐变弯箭头:方法1用
geom_link自动处理路径渐变;方法2通过拆分曲线为多个线段,每个线段对应一个渐变颜色值,实现近似渐变效果。 - 环形箭头组:通过计算三个间隔120度的弧形箭头坐标,用
geom_curve绘制首尾相连的顺时针环形,曲率设为0.5让曲线贴合圆形。 - 地图优化:调整
coord_sf的坐标范围,聚焦东海岸区域,让箭头和环形更突出。
内容的提问来源于stack exchange,提问作者Seth W. Bigelow
相关产品推荐
相关产品推荐

