You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于太阳高度在ggplot2中动态调整绘图背景颜色?

实现动态昼夜遮罩图层的方案

核心思路

利用已计算的太阳高度值,创建覆盖整个绘图范围的动态遮罩图层:

  • 太阳高度>0时(白天):遮罩透明度极低,几乎不影响地图显示
  • 太阳高度<0时(夜晚):遮罩透明度随太阳高度降低而升高(太阳高度越低,夜晚越暗),用深色填充模拟夜间效果

修改后的完整代码

library(ggplot2)
library(gganimate)
library(sf)
library(suncalc)
library(ggspatial)  
library(gifski)
library(prettymapr)

# 模拟数据
set.seed(123)
gps_data_sf <- data.frame(
  IMEI = rep(35664665, 300),  
  Pick.Time = seq.POSIXt(as.POSIXct("2024-08-13 00:00:00"), by = "15 mins", length.out = 300),
  Longitude = runif(300, 2.7, 2.8),
  Latitude = runif(300, 51.1, 51.2),
  Bird = rep("Bird A", 300)
)

# 添加太阳高度数据
gps_data_sf$sunheight <- mapply(function(lat, lon, time) {
  sun_position <- getSunlightPosition(date = time, lat = lat, lon = lon)
  return(sun_position$altitude) 
}, gps_data_sf$Latitude, gps_data_sf$Longitude, gps_data_sf$Pick.Time)

# 转换为sf格式
gps_data_sf <- st_as_sf(gps_data_sf, coords = c("Longitude", "Latitude"), crs = 4326)

# 创建昼夜遮罩图层数据:覆盖整个数据范围的多边形,绑定每个时间点的太阳高度
bbox <- st_bbox(gps_data_sf)
mask_poly <- st_as_sfc(bbox)
mask_data <- data.frame(
  Pick.Time = gps_data_sf$Pick.Time,
  sunheight = gps_data_sf$sunheight
) %>%
  st_sf(geometry = mask_poly, crs = 4326)

# 创建动画绘图
animated_plot <- ggplot() +
  annotation_map_tile(type = "osm", zoom = 12) + 
  # 添加动态昼夜遮罩:根据太阳高度调整透明度和填充色
  geom_sf(data = mask_data, aes(alpha = ifelse(sunheight >= 0, 0.05, abs(sunheight)/10)), 
          fill = "darkslategray", color = NA) +
  # 固定透明度范围,避免动态变化出现异常
  scale_alpha_continuous(range = c(0.05, 0.8), limits = c(0, 0.8)) +
  # 绘制GPS轨迹点
  geom_sf(data = gps_data_sf, aes(geometry = geometry, color = Bird, group = Bird), size = 5, alpha = 0.8) +
  labs(
    title = "物种移动轨迹(动态昼夜)",
    subtitle = "时间: {frame_time}",
    x = "经度",
    y = "纬度"
  ) +
  transition_time(Pick.Time) + 
  ease_aes('linear') +
  # 隐藏透明度图例(可选)
  guides(alpha = "none")

# 渲染动画
animate(animated_plot, nframes = 100, fps = 10, width = 800, height = 600, renderer = gifski_renderer())

关键细节说明

  1. 遮罩图层创建:通过数据的边界框生成覆盖整个绘图区域的多边形,确保每个时间点的遮罩都能完全覆盖地图
  2. 透明度逻辑:
    • 白天(太阳高度≥0):透明度设为0.05,几乎不遮挡地图
    • 夜晚(太阳高度<0):用abs(sunheight)/10计算透明度,太阳高度越低(绝对值越大),遮罩越暗
  3. 图层顺序:遮罩层放在地图和轨迹点之间,既实现昼夜效果,又保证轨迹点清晰可见
  4. 固定透明度范围:用scale_alpha_continuous锁定透明度区间,避免动画中出现过度透明或完全不透明的异常情况

内容的提问来源于stack exchange,提问作者reinoud

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 16:15:16