前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >mapboxGL实现室内地图

mapboxGL实现室内地图

作者头像
lzugis
发布2023-03-24 08:39:22
1.4K0
发布2023-03-24 08:39:22
举报
文章被收录于专栏:跟牛老师一起学WEBGIS

概述

本文分享如何通过mapboxGL实现三维的室内地图的展示。

效果

实现

1. 数据

精确的数需要通过CAD转换,本文为简单演示,是通过qgis中绘制的,数据主要包括如下字段:

代码语言:javascript
复制
{ "id": 1, "name": "type1","floor": 1, "type": "1" }

其中:

  • floor为楼层数据,建议为数字,方便排序;
  • type为类型,为商户的类型,通过type渲染不同的颜色;文中为了展示楼层地面,加了一个特殊的类型999,; 示例中用的完整数据如下:
代码语言:javascript
复制
{
"type": "FeatureCollection",
"features": [
{ "type": "Feature", "properties": { "id": 1, "name": "type1","floor": 1, "type": "1" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 113.88576766738845, 22.55132808900947 ], [ 113.88689629860265, 22.55132808900947 ], [ 113.888041775058838, 22.550081541101257 ], [ 113.887629066629771, 22.549550915978166 ], [ 113.887283739168709, 22.549525648115164 ], [ 113.886070881744502, 22.549727791019198 ], [ 113.885708709041452, 22.550089963722261 ], [ 113.88576766738845, 22.55132808900947 ] ] ] } },
{ "type": "Feature", "properties": { "id": 2, "name": "type3","floor": 1, "type": "3" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 113.888269185825877, 22.550536362635334 ], [ 113.888134423889866, 22.550511094772332 ], [ 113.887805941670806, 22.550789041265379 ], [ 113.887014215296674, 22.55160603550252 ], [ 113.886129840091513, 22.551597612881515 ], [ 113.885936119808491, 22.551841868890559 ], [ 113.885986655534495, 22.552692553611703 ], [ 113.886331982995557, 22.552540946433677 ], [ 113.887090018885687, 22.552321958287639 ], [ 113.887511149935747, 22.551892404616567 ], [ 113.887991239332834, 22.551437583082489 ], [ 113.888505019213923, 22.550949071064405 ], [ 113.888715584738961, 22.550957493685406 ], [ 113.888724007359954, 22.55067954719236 ], [ 113.8883871025199, 22.550452136425321 ], [ 113.888269185825877, 22.550536362635334 ] ] ] } },
{ "type": "Feature", "properties": { "id": 3, "name": "type2","floor": 1, "type": "2" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 113.886171953196524, 22.55290311913674 ], [ 113.887014215296674, 22.553736958615882 ], [ 113.887300584410724, 22.553602196679858 ], [ 113.887595376145768, 22.55366115502687 ], [ 113.889541001597095, 22.551791333164548 ], [ 113.889322013451064, 22.551504964050501 ], [ 113.88943150752408, 22.551353356872475 ], [ 113.889119870547034, 22.551142791347438 ], [ 113.888841924053978, 22.551125946105437 ], [ 113.887704870218784, 22.552246154698626 ], [ 113.887755405944802, 22.552473565465665 ], [ 113.887477459451745, 22.552642017885695 ], [ 113.886972102191663, 22.552515678570675 ], [ 113.886281447269539, 22.552768357200716 ], [ 113.886171953196524, 22.55290311913674 ] ] ] } },
{ "type": "Feature", "properties": { "id": 4, "name": "type3","floor": 2, "type": "3"}, "geometry": { "type": "Polygon", "coordinates": [ [ [ 113.88576766738845, 22.55132808900947 ], [ 113.88689629860265, 22.55132808900947 ], [ 113.888041775058838, 22.550081541101257 ], [ 113.887629066629771, 22.549550915978166 ], [ 113.887283739168709, 22.549525648115164 ], [ 113.886070881744502, 22.549727791019198 ], [ 113.885708709041452, 22.550089963722261 ], [ 113.88576766738845, 22.55132808900947 ] ] ] } },
{ "type": "Feature", "properties": { "id": 5, "name": "type2","floor": 2, "type": "2"}, "geometry": { "type": "Polygon", "coordinates": [ [ [ 113.888269185825877, 22.550536362635334 ], [ 113.888134423889866, 22.550511094772332 ], [ 113.887805941670806, 22.550789041265379 ], [ 113.887014215296674, 22.55160603550252 ], [ 113.886129840091513, 22.551597612881515 ], [ 113.885936119808491, 22.551841868890559 ], [ 113.885986655534495, 22.552692553611703 ], [ 113.886331982995557, 22.552540946433677 ], [ 113.887090018885687, 22.552321958287639 ], [ 113.887511149935747, 22.551892404616567 ], [ 113.887991239332834, 22.551437583082489 ], [ 113.888505019213923, 22.550949071064405 ], [ 113.888715584738961, 22.550957493685406 ], [ 113.888724007359954, 22.55067954719236 ], [ 113.8883871025199, 22.550452136425321 ], [ 113.888269185825877, 22.550536362635334 ] ] ] } },
{ "type": "Feature", "properties": { "id": 6, "name": "type1","floor": 2, "type": "1"}, "geometry": { "type": "Polygon", "coordinates": [ [ [ 113.886171953196524, 22.55290311913674 ], [ 113.887014215296674, 22.553736958615882 ], [ 113.887300584410724, 22.553602196679858 ], [ 113.887595376145768, 22.55366115502687 ], [ 113.889541001597095, 22.551791333164548 ], [ 113.889322013451064, 22.551504964050501 ], [ 113.88943150752408, 22.551353356872475 ], [ 113.889119870547034, 22.551142791347438 ], [ 113.888841924053978, 22.551125946105437 ], [ 113.887704870218784, 22.552246154698626 ], [ 113.887755405944802, 22.552473565465665 ], [ 113.887477459451745, 22.552642017885695 ], [ 113.886972102191663, 22.552515678570675 ], [ 113.886281447269539, 22.552768357200716 ], [ 113.886171953196524, 22.55290311913674 ] ] ] } },
{ "type": "Feature", "properties": { "id": 7, "name": "type2","floor": 3, "type": "2"}, "geometry": { "type": "Polygon", "coordinates": [ [ [ 113.88576766738845, 22.55132808900947 ], [ 113.88689629860265, 22.55132808900947 ], [ 113.888041775058838, 22.550081541101257 ], [ 113.887629066629771, 22.549550915978166 ], [ 113.887283739168709, 22.549525648115164 ], [ 113.886070881744502, 22.549727791019198 ], [ 113.885708709041452, 22.550089963722261 ], [ 113.88576766738845, 22.55132808900947 ] ] ] } },
{ "type": "Feature", "properties": { "id": 8, "name": "type3","floor": 3, "type": "3"}, "geometry": { "type": "Polygon", "coordinates": [ [ [ 113.888269185825877, 22.550536362635334 ], [ 113.888134423889866, 22.550511094772332 ], [ 113.887805941670806, 22.550789041265379 ], [ 113.887014215296674, 22.55160603550252 ], [ 113.886129840091513, 22.551597612881515 ], [ 113.885936119808491, 22.551841868890559 ], [ 113.885986655534495, 22.552692553611703 ], [ 113.886331982995557, 22.552540946433677 ], [ 113.887090018885687, 22.552321958287639 ], [ 113.887511149935747, 22.551892404616567 ], [ 113.887991239332834, 22.551437583082489 ], [ 113.888505019213923, 22.550949071064405 ], [ 113.888715584738961, 22.550957493685406 ], [ 113.888724007359954, 22.55067954719236 ], [ 113.8883871025199, 22.550452136425321 ], [ 113.888269185825877, 22.550536362635334 ] ] ] } },
{ "type": "Feature", "properties": { "id": 9, "name": "type1","floor": 3, "type": "1"}, "geometry": { "type": "Polygon", "coordinates": [ [ [ 113.886171953196524, 22.55290311913674 ], [ 113.887014215296674, 22.553736958615882 ], [ 113.887300584410724, 22.553602196679858 ], [ 113.887595376145768, 22.55366115502687 ], [ 113.889541001597095, 22.551791333164548 ], [ 113.889322013451064, 22.551504964050501 ], [ 113.88943150752408, 22.551353356872475 ], [ 113.889119870547034, 22.551142791347438 ], [ 113.888841924053978, 22.551125946105437 ], [ 113.887704870218784, 22.552246154698626 ], [ 113.887755405944802, 22.552473565465665 ], [ 113.887477459451745, 22.552642017885695 ], [ 113.886972102191663, 22.552515678570675 ], [ 113.886281447269539, 22.552768357200716 ], [ 113.886171953196524, 22.55290311913674 ] ] ] } },
{ "type": "Feature", "properties": { "id": 10, "name": "","floor": 1, "type": "999"}, "geometry": { "type": "Polygon", "coordinates": [ [ [ 113.885632905452397, 22.552818892926712 ], [ 113.885771878698918, 22.553046303693751 ], [ 113.886302503822009, 22.553484279985827 ], [ 113.887106864127674, 22.554212836702447 ], [ 113.887443768967728, 22.554246527186454 ], [ 113.888075465542826, 22.55364430978485 ], [ 113.888214438789362, 22.553412687707311 ], [ 113.890008457062649, 22.551715529575528 ], [ 113.889991611820648, 22.55150075273999 ], [ 113.88778909642879, 22.549538282046655 ], [ 113.88754484041975, 22.549454055836641 ], [ 113.887182667716687, 22.549407731421134 ], [ 113.886353039548055, 22.54956776122016 ], [ 113.885784512630451, 22.549727791019198 ], [ 113.88556552448442, 22.550098386343258 ], [ 113.885632905452397, 22.552818892926712 ] ] ] } },
{ "type": "Feature", "properties": { "id": 11, "name": "","floor": 2, "type": "999"}, "geometry": { "type": "Polygon", "coordinates": [ [ [ 113.885632905452397, 22.552818892926712 ], [ 113.885771878698918, 22.553046303693751 ], [ 113.886302503822009, 22.553484279985827 ], [ 113.887106864127674, 22.554212836702447 ], [ 113.887443768967728, 22.554246527186454 ], [ 113.888075465542826, 22.55364430978485 ], [ 113.888214438789362, 22.553412687707311 ], [ 113.890008457062649, 22.551715529575528 ], [ 113.889991611820648, 22.55150075273999 ], [ 113.88778909642879, 22.549538282046655 ], [ 113.88754484041975, 22.549454055836641 ], [ 113.887182667716687, 22.549407731421134 ], [ 113.886353039548055, 22.54956776122016 ], [ 113.885784512630451, 22.549727791019198 ], [ 113.88556552448442, 22.550098386343258 ], [ 113.885632905452397, 22.552818892926712 ] ] ] } },
{ "type": "Feature", "properties": { "id": 12, "name": "","floor": 3, "type": "999"}, "geometry": { "type": "Polygon", "coordinates": [ [ [ 113.885632905452397, 22.552818892926712 ], [ 113.885771878698918, 22.553046303693751 ], [ 113.886302503822009, 22.553484279985827 ], [ 113.887106864127674, 22.554212836702447 ], [ 113.887443768967728, 22.554246527186454 ], [ 113.888075465542826, 22.55364430978485 ], [ 113.888214438789362, 22.553412687707311 ], [ 113.890008457062649, 22.551715529575528 ], [ 113.889991611820648, 22.55150075273999 ], [ 113.88778909642879, 22.549538282046655 ], [ 113.88754484041975, 22.549454055836641 ], [ 113.887182667716687, 22.549407731421134 ], [ 113.886353039548055, 22.54956776122016 ], [ 113.885784512630451, 22.549727791019198 ], [ 113.88556552448442, 22.550098386343258 ], [ 113.885632905452397, 22.552818892926712 ] ] ] } }
]
}

对上面的数据加以处理,添加heightbase字段,用以展示楼层3d效果。

代码语言:javascript
复制
let floors = []
const floorHeight = 55, buildHeight = 7, baseHeight = 1
res.features.forEach(feature => {
  const {properties} = feature
  const {floor, type} = properties
  if(!floors.includes(floor)) floors.push(floor)
  let height = (floor - 1) * floorHeight + buildHeight
  let base = height - buildHeight
  if(type === '999') height = base + baseHeight
  properties.height = height
  properties.base = base
})

2. 添加图层

通过mapboxGL中的fill-extrusion图层实现楼层和商户的展示,初始化style如下:

代码语言:javascript
复制
const style = {
  version: 8,
  glyphs: "https://lzugis.cn/fonts/{fontstack}/{range}.pbf",
  sources: {
    'building': {
      type: 'geojson',
      data: res
    }
  },
  layers: [
    {
      "id": "sky",
      "type": "sky",
      "paint": {
        "sky-gradient": "rgba(0, 0, 0, 1)",
        "sky-opacity": 0.1
      }
    },
    {
      'id': 'building',
      'source': 'building',
      'type': 'fill-extrusion',
      'filter': ["==", ['get', 'floor'], 0],
      'paint': {
        'fill-extrusion-color': [
          'match',
          ['get', 'type'],
          '999', '#ccc',
          '1', '#FFD273',
          '2', '#E86D68',
          '#A880FF'
        ],
        'fill-extrusion-base': ['get', 'base'],
        'fill-extrusion-height': ['get', 'height'],
        'fill-extrusion-opacity': 0.45
      }
    },
    {
      'id': 'building-height',
      'source': 'building',
      'type': 'fill-extrusion',
      'filter': ["==", ['get', 'floor'], 0],
      'paint': {
        'fill-extrusion-color': '#0ff',
        'fill-extrusion-base': ['get', 'base'],
        'fill-extrusion-height': ['get', 'height'],
        'fill-extrusion-opacity': 0.45
      }
    },
    {
      'id': 'building-label',
      'type': 'symbol',
      'source': 'building',
      'filter': ["==", ['get', 'floor'], 0],
      'layout': {
        'text-field': ['get', 'name'],
        "text-size": 14
      },
      paint: {
        'text-color': '#999'
      }
    }
  ]
}

地图的初始化配置如下:

代码语言:javascript
复制
{
      container: 'map',
      center: [113.88768248794844, 22.551640034479163],
      hash: false,
      zoom: 16.6,
      style,
      pitch: 65,
      bearing: 120
}

3. 添加楼层控制UI

此处,单楼层和展示全部楼层的fill-extrusion-basefill-extrusion-height配置有区别。

代码语言:javascript
复制
const ul = document.createElement('ul')
ul.classList.add('floor-control')
const showFloor = (floor = 'All') => {
  floor = floor === 'All' ? floor : parseInt(floor)
  const lis = ul.children
  for (let i = 0; i < lis.length; i++) {
    const li = lis[i]
    li.classList.remove('active')
    if(floors.indexOf(floor) === i) li.classList.add('activ
  }
  map.setFilter('building', [floor === 'All' ? '!=' : '==',
  map.setFilter('building-label', ['==', ['get', 'floor'], 
  if(floor === 'All') {
    map.setPaintProperty('building', 'fill-extrusion-base',
    map.setPaintProperty('building', 'fill-extrusion-height
    map.setPaintProperty('building-height', 'fill-extrusion
    map.setPaintProperty('building-height', 'fill-extrusion
  } else {
    map.setPaintProperty('building', 'fill-extrusion-base',
    map.setPaintProperty('building', 'fill-extrusion-height
      'match',
      ['get', 'type'],
      '999', baseHeight,
      buildHeight
    ]);
    map.setPaintProperty('building-height', 'fill-extrusion
    map.setPaintProperty('building-height', 'fill-extrusion
      'match',
      ['get', 'type'],
      '999', baseHeight,
      buildHeight
    ]);
  }
}
const addFloorsUI = function () {
  floors.splice(0, 0, 'All')
  floors.forEach(floor => {
    const li = document.createElement('li')
    ul.appendChild(li)
    li.innerText = floor === 'All' ? floor : floor + 'F'
    li.setAttribute('floor', floor)
    li.onclick = function () {
      const floor = this.getAttribute('floor')
      showFloor(floor)
    }
  })
  document.body.appendChild(ul)
  showFloor()
}
map.on('load', addFloorsUI)

4. 添加点击交互

注册地图的click事件,用以取消选中,注册图层的click事件,用以选中。

代码语言:javascript
复制
map.on('click', e => {
  map.setFilter('building-height', ['==', ['get', 'id'], null]);
})
map.on('click', 'building', e => {
  const { properties } = e.features[0]
  let {id, type} = properties
  id = type === '999' ? null : id
  map.setFilter('building-height', ['==', ['get', 'id'], id]);
})
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-03-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 效果
  • 实现
    • 1. 数据
      • 2. 添加图层
      • 3. 添加楼层控制UI
      • 4. 添加点击交互
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档