mapbox-gl实现白膜立体建筑

311 阅读3分钟

有时候我们只有二维的面数据,怎么实现类似高德地图中的白膜立体建筑呢?在mapbox-gl中很容易实现,具体如下。 要在Vue中结合Mapbox显示自定义的GeoJSON数据,并实现建筑物的白膜效果,我们需要执行以下步骤:

  1. 安装Mapbox GL JS
  2. 创建Vue组件并加载Mapbox地图
  3. 添加自定义GeoJSON数据源
  4. 设置fill-extrusion图层来渲染建筑物
  5. 设置样式以实现白膜效果

1. 安装Mapbox GL JS

首先需要安装 mapbox-gl 包:

npm install mapbox-gl

2. 创建Vue组件

在Vue组件中,我们将配置并初始化Mapbox地图。

<template>
  <div ref="mapContainer" class="map-container"></div>
</template>

<script>
import mapboxgl from 'mapbox-gl';

export default {
  name: 'MapComponent',
  data() {
    return {
      map: null, // 地图实例
      geojsonData: {
        type: 'FeatureCollection',
        features: [
          {
            type: 'Feature',
            geometry: {
              type: 'Polygon',
              coordinates: [
                [
                  [118.997, 40.730],
                  [118.996, 40.731],
                  [118.995, 40.730],
                  [118.996, 40.729],
                  [118.997, 40.730]
                ]
              ]
            },
            properties: {
              height: 100, // 建筑物的高度
              min_height: 10, // 建筑物的最小高度
            }
          }
        ]
      }
    };
  },
  mounted() {
    this.initMap();
  },
  methods: {
    initMap() {
      mapboxgl.accessToken = 'your_mapbox_access_token_here'; // 替换为您的Mapbox访问令牌

      // 初始化地图
      this.map = new mapboxgl.Map({
        container: this.$refs.mapContainer,
        style: 'mapbox://styles/mapbox/streets-v11', // 使用Mapbox默认样式
        center: [118.995, 40.730], // 初始视角
        zoom: 15, // 初始缩放级别
      });

      // 在地图加载完成后添加自定义的GeoJSON数据
      this.map.on('load', () => {
        // 添加GeoJSON数据源
        this.map.addSource('custom-buildings', {
          type: 'geojson',
          data: this.geojsonData, // 使用自定义的GeoJSON数据
        });

        // 添加建筑物层(白膜效果)
        this.map.addLayer({
          id: '3d-buildings',
          type: 'fill-extrusion',
          source: 'custom-buildings',
          paint: {
            'fill-extrusion-color': '#ffffff', // 设置白膜颜色
            'fill-extrusion-opacity': 0.6, // 设置透明度
            'fill-extrusion-height': ['get', 'height'], // 高度设置
            'fill-extrusion-base': ['get', 'min_height'], // 基础高度
          }
        });

        // 可选:设置光源,让建筑物更具立体感
        this.map.setLight({
          anchor: 'viewport',
          color: '#ffffff',
          intensity: 0.8,
        });
      });
    }
  },
  beforeDestroy() {
    if (this.map) {
      this.map.remove();
    }
  }
};
</script>

<style scoped>
.map-container {
  width: 100%;
  height: 100vh;
}
</style>

3. 代码解释

  • Mapbox初始化: 使用Mapbox GL JS在mounted钩子中初始化地图,并指定地图容器、样式、中心点和缩放级别。

  • 自定义GeoJSON数据: 自定义的建筑物数据存储在geojsonData对象中,其中每个建筑物都有heightmin_height属性,分别表示建筑物的高度和最小高度。

  • 添加GeoJSON数据源: 在地图加载后,我们通过 map.addSource 添加自定义的GeoJSON数据源,并通过fill-extrusion类型的图层展示建筑物。

  • 白膜效果

    • 使用fill-extrusion-color设置建筑物的颜色为白色。
    • 使用fill-extrusion-opacity设置透明度。
    • 使用fill-extrusion-heightfill-extrusion-base分别设置建筑物的实际高度和基础高度。
  • 光照效果: 使用map.setLight调整光源,使建筑物呈现更具立体感的效果。

mapbox-gl.png

4. 运行效果

  • 地图显示中心会在[ 118.996, 40.730 ]处,并加载自定义的GeoJSON数据。
  • 该GeoJSON数据表示一个建筑物,其高度为100米,最小高度为10米。
  • 建筑物会呈现白色的透明效果(即白膜效果),并根据设置的光照和透明度显示。

5. 可选的增强

  • 动态添加和更新数据: 如果您需要动态更新GeoJSON数据,您可以通过 map.getSource('custom-buildings').setData(newGeojsonData) 来更新数据源。

  • 交互: 可以在地图上添加交互功能,例如点击建筑物时高亮显示,或弹出详细信息框。

  • 多建筑物支持: GeoJSON数据中可以包含多个建筑物,只需在 geojsonData.features 中添加多个建筑物对象即可。

总结

这段代码展示了如何在Vue中结合Mapbox GL JS和自定义GeoJSON数据渲染建筑物,并实现白膜效果,想要更复杂的样式可以通过表达式来设置。