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

基于Mapbox GL 3D实现本地建筑阴影投影的技术咨询

本地实现Mapbox GL 3D建筑太阳阴影投影方案

核心思路

通过两个独立图层实现真实阴影效果:

  • 建筑本体层:用fill-extrusion渲染3D建筑实体
  • 阴影层:用支持模糊的fill图层,基于太阳角度为每个建筑计算专属投影偏移,替代简单的图层整体平移

步骤1:用SunCalc计算太阳参数

先获取目标时间的太阳高度角(altitude)和方位角(azimuth):

  • altitude为正代表太阳在地平线上方,<=0时无阴影
  • azimuth是从正北顺时针的弧度值,需转换为地图坐标系的偏移分量

核心计算公式:

// 建筑高度需和Mapbox坐标单位匹配(如米)
const shadowLength = height / Math.tan(altitude);
// 分解为东(x)、北(y)方向偏移
const xOffset = shadowLength * Math.sin(azimuth);
const yOffset = -shadowLength * Math.cos(azimuth);

步骤2:实现真实阴影投影

不用图层整体平移,而是给阴影层设置数据驱动的平移表达式,让每个建筑根据自身高度计算偏移:

  1. 新增fill类型阴影图层,与建筑本体层共享数据源
  2. 配置paint属性:
    • fill-color:半透明灰色(如rgba(0,0,0,0.2))
    • fill-blur:设置模糊半径(如5,数值越大模糊效果越强)
  3. 用表达式实现动态偏移,避免太阳高度极低时偏移量异常:
// 假设数据源中建筑高度字段为'height'
'fill-translate': [
  ['case',
    ['>', altitude, 0.1], // 太阳高度高于约5.7度时显示阴影
    ['*', ['get', 'height'], Math.sin(azimuth) / Math.tan(altitude)],
    0
  ],
  ['case',
    ['>', altitude, 0.1],
    ['*', ['get', 'height'], -Math.cos(azimuth) / Math.tan(altitude)],
    0
  ]
]

步骤3:优化阴影效果

  • 图层层级:阴影层置于建筑本体层下方(先添加阴影层,再添加建筑层)
  • 增强模糊:若单图层模糊不足,可叠加2-3个阴影层,每层偏移量微增、透明度递减,模拟自然软阴影
  • 无阴影处理:太阳高度<=0时,设置阴影层visibility: 'none'

代码示例片段

// 1. 获取太阳参数(示例:当前时间,北京坐标)
const date = new Date();
const lat = 39.9042;
const lon = 116.4074;
const sunPos = SunCalc.getPosition(date, lat, lon);
const { altitude, azimuth } = sunPos;

// 2. 添加阴影层
map.addLayer({
  id: 'building-shadow',
  type: 'fill',
  source: 'buildings', // 与建筑层同源
  paint: {
    'fill-color': 'rgba(0, 0, 0, 0.2)',
    'fill-blur': 5,
    'fill-translate': [
      ['case', ['>', altitude, 0.1], ['*', ['get', 'height'], Math.sin(azimuth) / Math.tan(altitude)], 0],
      ['case', ['>', altitude, 0.1], ['*', ['get', 'height'], -Math.cos(azimuth) / Math.tan(altitude)], 0]
    ]
  },
  layout: {
    visibility: altitude > 0 ? 'visible' : 'none'
  }
});

// 3. 添加建筑本体层
map.addLayer({
  id: 'building-3d',
  type: 'fill-extrusion',
  source: 'buildings',
  paint: {
    'fill-extrusion-color': '#aaa',
    'fill-extrusion-height': ['get', 'height'],
    'fill-extrusion-base': ['get', 'base_height'],
    'fill-extrusion-opacity': 0.8
  }
});

关键注意事项

  • 单位匹配:确保建筑高度单位(如米)与Mapbox Web墨卡托坐标单位一致,偏差过大需添加缩放系数
  • 性能优化:建筑数量极多时,可提前在数据源中预计算阴影偏移量,减少实时表达式计算损耗
  • 方向准确性:Mapbox的fill-translate中x为东向递增、y为北向递增,因此y偏移需取负(太阳在北时阴影向南)

内容的提问来源于stack exchange,提问作者Federico González Brizzio

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 22:07:43