室外渲染
BicMap 提供室外场景的渲染能力,包括三维建筑物渲染、高精地图(HD Map)数据加载和自定义瓦片地图接入。
源码参考
- 建筑物:
src/bicMap/core/mapFeatures/buildings.js- 示例:
src/examples/outdoor/buildings/index.vue- 示例:
src/examples/outdoor/hdMap/index.vue- 示例:
src/examples/outdoor/mapTiles/index.vue
createBuildings() — 三维建筑物渲染
基于 MapLibre fill-extrusion 图层渲染带高度的三维建筑物,支持高度缩放、透明度调节和颜色模式切换。
js
import { createBuildings } from '@x-humanoid-cloud/bic-map'
const ctrl = createBuildings(map, geojson, options)geojson 数据结构
输入标准 GeoJSON FeatureCollection,每个 Feature 支持以下属性字段:
js
{
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: [[[lng1,lat1],[lng2,lat2],[lng3,lat3],[lng1,lat1]]]
},
properties: {
height: 45, // 建筑总高度(米)
base_height: 0, // 底部高度(米),默认 0
color: '#90caf9', // 建筑颜色,可选
name: '综合楼 A' // 建筑名称,可选
}
}
]
}options 参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
defaultHeight | number | 20 | Feature 未指定 height 时的默认高度(米) |
defaultColor | string | '#90caf9' | Feature 未指定 color 时的默认填充色 |
opacity | number | 0.85 | 建筑不透明度(0–1) |
heightScale | number | 1 | 高度缩放倍数,2 表示高度翻倍 |
showOutline | boolean | false | 是否显示建筑轮廓线 |
outlineColor | string | '#42a5f5' | 轮廓线颜色 |
控制器方法
js
const ctrl = createBuildings(map, geojson, options)
ctrl.show() // 显示建筑物图层
ctrl.hide() // 隐藏建筑物图层
ctrl.setHeightScale(2.0) // 动态调整高度缩放倍数
ctrl.setOpacity(0.6) // 动态调整不透明度
ctrl.update(newGeojson) // 替换建筑数据并重新渲染
ctrl.remove() // 销毁图层,释放资源示例
js
import bicMap from '@x-humanoid-cloud/bic-map'
import { createBuildings } from '@x-humanoid-cloud/bic-map'
let map, buildingsCtrl
map = bicMap.createMap({
container: 'map',
center: [116.41, 39.90],
zoom: 16,
pitch: 55,
bearing: -15,
antialias: true
})
map.on('load', () => {
buildingsCtrl = createBuildings(map, buildingsGeojson, {
defaultHeight: 20,
defaultColor: '#90caf9',
opacity: 0.85,
heightScale: 1,
showOutline: true,
outlineColor: '#42a5f5'
})
})
// 动态调整高度
buildingsCtrl.setHeightScale(1.5)
// 切换显示/隐藏
buildingsCtrl.hide()
buildingsCtrl.show()
// 卸载时销毁
buildingsCtrl.remove()开启抗锯齿
三维建筑物渲染建议在 createMap 时传入 antialias: true,以获得更平滑的边缘效果。
高精地图(HD Map)
高精地图通过 GeoJSON 数据叠加多个 MapLibre 图层,精细渲染车道线、道路标线、路口图标等自动驾驶/机器人导航要素。
源码参考:
src/examples/outdoor/hdMap/index.vue
数据结构
高精地图通常由多个分类数据层组成:
| 数据层 | 说明 |
|---|---|
| 车道(lanes) | 行车道、自行车道等区域多边形 |
| 道路标线(markings) | 双黄线、虚线、实线等 |
| 转向标记(turn markers) | 直行、左转、右转箭头图标 |
| 路口标志(signs) | 禁行、限速等交通标志 |
加载 HD 车道图层
js
map.on('load', () => {
// 车道面
map.addSource('hd-lanes', { type: 'geojson', data: hdLanesGeojson })
map.addLayer({
id: 'hd-driving-lanes',
type: 'fill',
source: 'hd-lanes',
filter: ['==', ['get', 'lane_type'], 'driving'],
paint: {
'fill-color': '#d4e9ff',
'fill-opacity': 0.6
}
})
map.addLayer({
id: 'hd-bicycle-lanes',
type: 'fill',
source: 'hd-lanes',
filter: ['==', ['get', 'lane_type'], 'bicycle'],
paint: {
'fill-color': '#b2f5b2',
'fill-opacity': 0.6
}
})
// 道路标线
map.addSource('hd-markings', { type: 'geojson', data: hdMarkingsGeojson })
map.addLayer({
id: 'hd-markings-double-yellow',
type: 'line',
source: 'hd-markings',
filter: ['==', ['get', 'marking_type'], 'double_yellow'],
paint: { 'line-color': '#facc15', 'line-width': 2 }
})
map.addLayer({
id: 'hd-markings-dashed',
type: 'line',
source: 'hd-markings',
filter: ['==', ['get', 'marking_type'], 'dashed_white'],
paint: { 'line-color': '#fff', 'line-width': 1.5, 'line-dasharray': [4, 4] }
})
// 转向图标(需预加载图片到地图)
map.addSource('hd-turn-markers', { type: 'geojson', data: hdTurnMarkersGeojson })
map.addLayer({
id: 'hd-turn-icons',
type: 'symbol',
source: 'hd-turn-markers',
layout: {
'symbol-placement': 'point',
'icon-image': ['get', 'icon_name'], // 对应 map.addImage() 注册的图片名
'icon-size': 0.4,
'icon-rotation-alignment': 'map',
'icon-rotate': ['get', 'bearing']
}
})
})预加载图标资源
js
// 在加载 HD 图层前,先将图标注册到地图
async function loadHdIcons(map) {
const icons = [
{ name: 'icon-straight', url: '/assets/icons/icon-stright.svg' },
{ name: 'icon-turn-left', url: '/assets/icons/icon-turn-left.svg' },
{ name: 'icon-turn-right', url: '/assets/icons/icon-turn-right.svg' },
{ name: 'icon-traffic', url: '/assets/icons/icon-traffic.svg' },
]
for (const icon of icons) {
const img = await loadImage(icon.url)
map.addImage(icon.name, img)
}
}
function loadImage(url) {
return new Promise((resolve, reject) => {
const img = new Image()
img.onload = () => resolve(img)
img.onerror = reject
img.src = url
})
}地图瓦片加载
通过 MapLibre raster 数据源接入自定义瓦片地图服务(XYZ 格式),支持 OpenStreetMap、天地图、自建瓦片服务等。
源码参考:
src/examples/outdoor/mapTiles/index.vue
基本用法
js
const SOURCE_ID = 'custom-tiles'
const LAYER_ID = 'custom-tiles-layer'
map.on('load', () => {
map.addSource(SOURCE_ID, {
type: 'raster',
tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
tileSize: 256,
attribution: '© OpenStreetMap contributors'
})
map.addLayer({
id: LAYER_ID,
type: 'raster',
source: SOURCE_ID,
paint: {
'raster-opacity': 0.85,
'raster-fade-duration': 300
}
})
})动态切换瓦片
js
// 移除旧图层和数据源,再重新添加
function switchTileUrl(newUrl) {
if (map.getLayer(LAYER_ID)) map.removeLayer(LAYER_ID)
if (map.getSource(SOURCE_ID)) map.removeSource(SOURCE_ID)
map.addSource(SOURCE_ID, {
type: 'raster',
tiles: [newUrl],
tileSize: 256
})
map.addLayer({
id: LAYER_ID,
type: 'raster',
source: SOURCE_ID,
paint: { 'raster-opacity': 0.85 }
})
}调整透明度
js
map.setPaintProperty(LAYER_ID, 'raster-opacity', 0.6)常见瓦片服务 URL 格式
| 服务 | URL 模板 |
|---|---|
| OpenStreetMap | https://tile.openstreetmap.org/{z}/{x}/{y}.png |
| 天地图矢量(需 key) | https://t{0-7}.tianditu.gov.cn/vec_w/wmts?...&x={x}&y={y}&z={z} |
| 本地自建服务 | http://localhost:8080/tiles/{z}/{x}/{y}.png |

