mapbox高阶,结合threejs(threebox)实现立体三维飞线图
👨⚕️ 主页: gis分享者
👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅!
👨⚕️ 收录于专栏:mapbox 从入门到精通
文章目录
- 一、🍀前言
- 1.1 ☘️mapboxgl.Map 地图对象
- 1.2 ☘️mapboxgl.Map style属性
- 1.3 ☘️threebox Line静态对象
- 二、🍀使用threebox,实现立体三维飞线图
- 1. ☘️实现思路
- 2. ☘️代码样例
一、🍀前言
本文详细介绍如何基于mapbox-gl v3.*.* 版本,结合threejs(threebox)实现立体三维飞线图,亲测可用。希望能帮助到您。一起学习,加油!加油!
1.1 ☘️mapboxgl.Map 地图对象
mapboxgl.Map 地图对象。
构造函数:
new Map class(options: Object)
本例使用属性:
1.2 ☘️mapboxgl.Map style属性
本例使用属性:
- version:版本号,当前固定值为8。
- sources:数据源集合(必填,用于包含一系列数据源
source,这些数据源提供了在地图上显示的数据)。值为{}对象。{}中的属性名是数据源的名称。
每个数据源 source 有的属性:
type:数据源类型
tiles:数据源地址
tileSize:数据源切片大小 - layers:图层集合(必填,包含了一系列图层 layer,这些图层指定了如何渲染数据源提供的数据)
每个layer的属性(当前示例用到的):
id:图层id
type:图层类型
source:数据源名称
1.3 ☘️threebox Line静态对象
tb.line(options);
在整个三维空间中向地图添加一条线。颜色渲染独立于场景照明。在内部,调用自定义线着色器。
option | 是否必填 | 默认值 | 类型 | 说明 |
---|---|---|---|---|
geometry | 是 | NA | lineGeometry | 绘制线条的经纬度坐标数组 |
color | 否 | black | color | 线条的颜色。与其他Threebox对象不同,无论场景照明如何,此颜色都将在屏幕上精确渲染 |
width | 否 | 1 | number | 线条宽度。与其他Threebox对象不同,此宽度以显示像素为单位,而不是米或场景单位。 |
opacity | 否 | 1 | number | 线的透明度 |
threebox_API
二、🍀使用threebox,实现立体三维飞线图
1. ☘️实现思路
- 1、引入’mapbox-gl’、'mapbox-gl/dist/mapbox-gl.css’、‘threebox-plugin’文件
- 2、添加id为map的html页面要素,定义map样式。
- 3、定义initMap初始化地图方法,方法内创建mapboxgl.Map地图对象map。map绑定‘style.load’事件,在load回调事件内部,map添加自定义图层,自定义图层onAdd方法内实现三维飞线的添加,具体代码参考代码样例。在mounted钩子函数中调用initMap方法。
2. ☘️代码样例
<template>
<div id='map'></div>
</template>
<script>
/** 迁徙线 **/
import mapboxgl from 'mapbox-gl'
import 'mapbox-gl/dist/mapbox-gl.css'
import { Threebox } from 'threebox-plugin'
export default {
name: 'ThreeBoxMigrateLine',
data () {
return {
map: null
}
},
mounted () {
this.$nextTick(() => {
this.initMap()
})
},
methods: {
initMap () {
mapboxgl.accessToken = 'mapbox官网注册token'
this.map = new mapboxgl.Map({
container: 'map',
zoom: 2,
minZoom: 0,
pitch: 45,
center: [116.4, 39.9],
style: 'mapbox://styles/mapbox/light-v10'
})
let self = this
this.map.on('load', function () {
let lines = self.getMigrateLineData()
self.map.addLayer({
id: 'custom_layer',
type: 'custom',
renderingMode: '3d',
onAdd: function (map, mbxContext) {
window.tb = new Threebox(
map,
mbxContext,
{defaultLights: true}
)
for (let line of lines) {
var lineOptions = {
geometry: line,
color: (line[1][1] / 180) * 0xffffff,
width: Math.random() + 1
}
let lineMesh = window.tb.line(lineOptions)
window.tb.add(lineMesh)
}
},
render: function () {
window.tb.update()
}
})
})
},
getMigrateLineData () {
var lines = new Array()
// 25个坐标过渡点
var arcSegments = 25
// 50条飞线
var lineQuantity = 50
for (var i = 0; i < lineQuantity; i++) {
var line = new Array()
// 目标点坐标
var destination = [300 * (Math.random() - 0.5), 140 * (Math.random() - 0.5)]
// 最大高度
var maxElevation = Math.pow(Math.abs(destination[0] * destination[1]), 0.5) * 80000
var increment = destination.map(function (direction) {
return direction / arcSegments
})
for (var l = 0; l <= arcSegments; l++) {
var waypoint = []
if (l === 0) {
// 飞线起点坐标
waypoint = [116.4, 39.9]
// waypoint = [0, 0]
} else {
waypoint = increment.map(function (direction) {
return direction * l
})
waypoint = [waypoint[0] + 116.4, waypoint[1] + 39.9]
}
var waypointElevation = Math.sin(Math.PI * l / arcSegments) * maxElevation
waypoint.push(waypointElevation)
line.push(waypoint)
}
lines.push(line)
}
return lines
}
}
}
</script>
<style scoped>
#map{
height: 100vh;
width: 100vw;
}
</style>
效果如下: