这里使用的是vue-cli创建的vue3项目
安装依赖
高德地图
npm i @amap/amap-jsapi-loader -s
ThreeJS (version:139)
npm i three -s
代码
在看Vue代码之前可以看看官网demo的写法,可以两份对比的看
自定义图层-GLCustomLayer 结合 THREE
下面是Vue的代码
<template>
<div ref="mapRef" id="container"></div>
</template>
<script setup>
import * as AMapLoader from "@amap/amap-jsapi-loader";
import * as THREE from "three";
import {nextTick, onMounted, ref} from "vue";
/* refs */
// 地图dom
const mapRef = ref()
//地图中心点
const center = [121.407394, 37.424985]
// 地图对象
let map = null
// 高德地图类
let AMap = null
// 渲染器
let render = null
// 场景
let scene = null
// 相机
let camera = null
// 坐标转换器(经纬度转three位置)
let customCoords = null
// 转化后的中心点坐标
let comLocation = null
function initScene() {
// 初始化场景
scene = new THREE.Scene();
}
// 初始化光源
function initLight() {
// 创建环境光
let light = new THREE.AmbientLight(0xffffff, 1);
light.position.set(0, 0, 0); //点光源位置
scene.add(light);
}
// 初始化相机
function initCamera() {
camera = new THREE.PerspectiveCamera(
60,
mapRef.value.offsetWidth / mapRef.value.offsetHeight,
100,
1 << 30
);
}
// 添加盒子
function addBox() {
let mat = new THREE.MeshLambertMaterial({
side: THREE.DoubleSide,
color: 0x1e2f97,
transparent: true,
opacity: .4,
depthWrite: false
});
let geo = new THREE.BoxBufferGeometry(30, 30, 30);
let mesh = new THREE.Mesh(geo, mat);
mesh.position.set(comLocation[0], comLocation[1], 15);
scene.add(mesh);
}
// 动画
function animate() {
// 渲染时刷新地图
map.render();
// 自动刷新
requestAnimationFrame(animate);
}
// 初始化树
function initThree() {
// 初始化数据转换工具
customCoords = map.customCoords;
// 数据使用转换工具进行转换,这个操作必须要提前执行(在获取镜头参数 函数之前执行),否则将会获得一个错误信息。
comLocation = customCoords.lngLatToCoord(center);
// 创建webgl layer
let glLayer = new AMap.GLCustomLayer({
// 图层的层级 这里写的太大模型会消失
zIndex: 10,
// 初始化的操作,创建图层过程中执行一次。
init: (gl) => {
render = new THREE.WebGLRenderer({
context: gl
})
// 自动清空画布这里必须设置为 false,否则地图底图将无法显示
render.autoClear = false;
initScene()
initLight()
initCamera()
// 添加盒子 如果不延迟 或者延迟时间少了会保一个警告(Vertex buffer is not big enough for the draw call)
setTimeout(() => {
addBox()
}, 500)
},
render: () => {
render.state.reset()
const {near, far, fov, up, lookAt, position} =
customCoords.getCameraParams();
camera.near = near;
camera.far = far;
camera.fov = fov;
camera.position.set(...position);
camera.up.set(...up);
camera.lookAt(...lookAt);
camera.updateProjectionMatrix();
render.render(scene, camera);
},
})
map.add(glLayer)
animate()
}
// 初始化地图
function initMap() {
AMapLoader.load({
key: 'dae9f17b30c2fcce6c38fafc61c77f52',//首次load必填
version: '2.0'
}).then((_AMap) => {
AMap = _AMap
map = new AMap.Map('container', {
viewMode: '3D', // 地图模式
mapStyle: 'amap://styles/grey',
pitch: 55,
zoom: 18,
center: center,
// 只显示的特征
features: ['bg', 'road', 'building']
});
initThree()
}).catch((e) => {
console.error(e);
});
}
onMounted(() => {
nextTick(() => {
initMap()
})
})
</script>
<style lang="scss">
html, body {
margin: 0;
padding: 0;
}
#container {
height: 100vh;
}
</style>