作为一个前端小白,今天要开始学习百度地图的 JSAPI Three(也叫 mapvthree)了!听说这是一个超强的 3D 地图渲染引擎,可以做出很酷炫的三维地图效果。想想就激动!让我记录下学习的过程吧!
第一天:听说 JSAPIThree
今天在项目里看到了一个新需求,要用 3D 地图展示数据。我一开始还以为是普通的百度地图 API,结果同事说要用 JSAPIThree,这是百度地图的 3D 渲染引擎。
我的第一反应:3D 地图?听起来好高级!但是会不会很难啊?
查了一下资料才知道:
- JSAPIThree = 百度地图 JSAPI Three
- 也叫
mapvthree(这是 npm 包名) - 基于 Three.js 开发
- 可以做二三维一体化的地图渲染
我的理解:简单说就是百度地图的 3D 版本,可以做出那种很酷炫的三维地图效果,就像游戏里的地图一样!
第二天:开始安装
第一步:安装依赖
按照文档,第一步是安装依赖。文档说需要安装两个包:
@baidumap/mapv-three:这是 JSAPIThree 的核心包three:这是 Three.js,底层渲染引擎
npm i -S @baidumap/mapv-three three
我的操作:打开终端,执行命令...等待中...
我的发现:安装成功了!但是看到依赖列表里有很多包,看来这个库还挺大的。
注意:文档说如果用 pnpm v7 以上版本,可能会有警告,需要执行 pnpm approve-builds。我用的是 npm,所以没遇到这个问题。
第二步:配置静态资源
安装完依赖后,我以为就能直接用了,结果文档说还要配置静态资源!
我的困惑:什么是静态资源?为什么要配置?
看了文档才知道,mapvthree 在初始化时需要加载一些资源文件(比如着色器、纹理等)。如果不配置,运行时会报错:
"Unable to determine base URL automatically, try defining a global variable called MAPV_BASE_URL."
我的理解:就是告诉引擎,资源文件在哪里。
我用的是 Vite
文档说如果用 Vite 或 Rollup,需要这样配置:
// vite.config.js
import copy from 'rollup-plugin-copy';const viteConfig = {plugins: [copy({targets: [{src: 'node_modules/@baidumap/mapv-three/dist/assets', dest: 'public/mapvthree'},],verbose: true,hook: 'buildStart',}),// ...其他插件]
};
我的操作:
- 先安装
rollup-plugin-copy:npm i -D rollup-plugin-copy - 在
vite.config.js里添加配置 - 重启开发服务器
我的感受:配置过程有点复杂,但是按照文档一步步来,还是能搞定的!
在 HTML 里声明全局变量
配置完构建工具后,还要在 index.html 里声明全局变量:
<!-- index.html -->
<script>window.MAPV_BASE_URL = 'mapvthree/';
</script>
我的理解:这个变量告诉引擎,资源文件在 mapvthree/ 目录下。
我的操作:在 index.html 的 <head> 里加上这段代码。
第三步:配置百度地图 AK
文档说 mapvthree 默认展示百度地图矢量数据,需要配置百度地图开发者密钥(AK)。
我的疑问:什么是 AK?为什么要配置?
查了一下才知道,AK 是百度地图开放平台的密钥,用来验证身份和限制访问量。
我的操作步骤:
- 访问百度地图开放平台
- 登录百度账号(没有的话要注册)
- 点击"创建应用"
- 填写应用名称,选择"浏览器端"
- 创建完成后,获得一个 AK 密钥
我的感受:注册和创建应用的过程还挺顺利的,就是要注意选择"浏览器端",不然可能用不了。
在代码里配置 AK
拿到 AK 后,要在项目入口文件里配置:
// 在项目入口文件中配置(比如 main.js)
import * as mapvthree from '@baidumap/mapv-three';// 配置百度地图 AK
mapvthree.BaiduMapConfig.ak = '您的AK密钥';
我的操作:在 main.js 里加上这段代码,把 '您的AK密钥' 替换成我申请的 AK。
我的发现:这个配置只需要全局执行一次就行,不用每次都配置。
第三天:第一个 Hello World!
配置完成后,终于可以开始写代码了!我按照文档写了个最简单的例子。
第一步:引入库
文档说可以一次性引入所有组件,也可以按需引入。我选择一次性引入,简单直接:
import * as mapvthree from '@baidumap/mapv-three';
我的想法:先全部引入,等熟悉了再考虑按需引入优化。
第二步:初始化引擎
文档说通过 Engine 类可以初始化一个三维场景。最简单的用法是:
const container = document.getElementById('container');
const engine = new mapvthree.Engine(container, {// 可选的配置项
});
我的理解:就像创建一个画布,container 是容器元素,engine 是引擎实例。
我的第一个尝试:
import * as mapvthree from '@baidumap/mapv-three';// 获取容器元素
const container = document.getElementById('container');// 创建引擎
const engine = new mapvthree.Engine(container);
我的发现:运行后,页面上出现了一个 3D 地图!虽然很简单,但是能看到地图了,好激动!
我的观察:
- 默认有百度矢量底图
- 默认有天空(看起来像真实的天空)
- 可以鼠标拖动旋转视角
- 可以滚轮缩放
我的感受:太神奇了!就几行代码,就能看到一个 3D 地图!
第三步:了解配置选项
看到效果后,我开始好奇:能不能自定义地图的位置、视角?
文档说可以在初始化时传入配置:
const engine = new mapvthree.Engine(container, {map: {center: [116.414, 39.915], // 中心点坐标(经度,纬度)range: 500, // 缩放级别(米)heading: 225, // 方位角(度)pitch: 70, // 俯仰角(度)},
});
我的尝试:
const engine = new mapvthree.Engine(container, {map: {center: [116.404, 39.915], // 北京天安门range: 1000, // 1000 米高度heading: 0, // 正北方向pitch: 60, // 60 度俯视},
});
我的发现:地图定位到了天安门,视角也变了!pitch 越大,俯视角度越大,看起来越像从高空往下看。
我的理解:
center:地图中心点的经纬度range:相机距离地面的高度(米),值越小越近heading:水平旋转角度,0 是正北,90 是正东pitch:垂直俯仰角,0 是水平,90 是垂直向下
第四步:添加可视化组件
看到地图后,我想:能不能在地图上添加一些点?
文档说可以用 SimplePoint 来展示点数据。但是需要先准备数据源。
我的第一次尝试:
// 创建数据源
const dataSource = new mapvthree.GeoJSONDataSource.fromGeoJSON({type: 'FeatureCollection',features: [{type: 'Feature',properties: {},geometry: {type: 'Point',coordinates: [116.414, 39.915], // 一个点的坐标},},],
});// 创建点图层
const point = engine.add(new mapvthree.SimplePoint({size: 10, // 点的大小
}));// 关联数据源
point.dataSource = dataSource;
我的发现:地图上出现了一个红色的点!虽然很小,但是能看到!
我的感受:成功添加了点!虽然代码有点长,但是逻辑很清晰:
- 准备数据(GeoJSON 格式)
- 创建图层
- 关联数据
我的改进:我想添加多个点,试试:
const dataSource = new mapvthree.GeoJSONDataSource.fromGeoJSON({type: 'FeatureCollection',features: [{type: 'Feature',properties: {},geometry: {type: 'Point',coordinates: [116.404, 39.915],},},{type: 'Feature',properties: {},geometry: {type: 'Point',coordinates: [116.414, 39.925],},},],
});const point = engine.add(new mapvthree.SimplePoint({size: 20, // 调大一点,看得清楚
}));
point.dataSource = dataSource;
我的发现:地图上出现了两个点!太棒了!
第五步:添加三维模型
看到点数据后,我想:能不能添加 3D 模型?比如建筑物?
文档说可以用 SimpleModel 来加载 3D 模型:
const model = engine.add(new mapvthree.SimpleModel({name: 'model',point: [116.414, 39.915], // 模型的位置url: 'assets/models/building/5_tiyuzhongxin.glb', // 模型文件路径
}));
我的尝试:我找了个 GLB 格式的模型文件,按照文档写代码:
const model = engine.add(new mapvthree.SimpleModel({name: 'myBuilding',point: [116.404, 39.915], // 天安门附近url: 'assets/models/building/5_tiyuzhongxin.glb',
}));
我的发现:地图上出现了一个 3D 建筑模型!可以旋转视角看,太酷了!
我的感受:3D 模型在地图上看起来特别真实,就像真的建筑物一样!
我的疑问:模型文件格式有什么要求?
查了文档才知道,支持常见的 3D 模型格式:
- GLTF/GLB(推荐)
- OBJ
- FBX
我的理解:GLB 是 GLTF 的二进制版本,文件更小,加载更快,所以推荐用 GLB。
第六步:添加交互事件
看到模型后,我想:能不能点击交互?
文档说可以添加事件监听:
point.addEventListener('click', (e) => {console.log('点击了!', e);
});
我的尝试:
point.addEventListener('click', (e) => {console.log('点击了点的数据:', e);alert('你点击了一个点!');
});
我的发现:点击点的时候,控制台输出了事件信息,还弹出了提示框!
我的感受:交互功能也很简单,就是标准的 addEventListener!
我的改进:我想在点击时显示更多信息:
point.addEventListener('click', (e) => {const coordinates = e.feature.geometry.coordinates;console.log('点击的坐标:', coordinates);alert(`经度:${coordinates[0]}\n纬度:${coordinates[1]}`);
});
我的发现:可以获取点击的坐标信息!这样就能做更多交互了!
第四天:深入了解引擎
发现引擎的属性
看了文档才知道,engine 对象有很多属性:
engine.map:地图相关操作(视野控制、坐标转换等)engine.rendering:渲染相关配置(动画循环、特效等)engine.widgets:UI 控件(指南针、比例尺等)engine.selection:模型选择控制器engine.clock:时钟管理(控制时间,影响天空、光照等)engine.camera:相机对象(Three.js 的相机)engine.renderer:渲染器对象(Three.js 的渲染器)engine.scene:场景对象(Three.js 的场景)
我的理解:engine 就像一个总控制器,管理着地图的各个方面。
尝试视野操作
文档说可以通过 engine.map 控制视野:
const center = [116.404, 39.915];
engine.map.lookAt(center, {heading: 0,pitch: 60,range: 2000,
});
我的尝试:
// 创建一个按钮,点击后飞到天安门
document.getElementById('flyToBtn').addEventListener('click', () => {engine.map.lookAt([116.404, 39.915], {heading: 0,pitch: 60,range: 1000,});
});
我的发现:点击按钮后,地图会平滑地移动到天安门!就像动画一样!
我的感受:这个功能太实用了!可以做场景切换、视角动画等效果!
尝试渲染配置
文档说可以通过 engine.rendering 配置渲染:
// 开启循环渲染(用于动画)
engine.rendering.enableAnimationLoop = true;// 设置帧率
engine.rendering.animationLoopFrameTime = 16; // 约 60 FPS
我的尝试:
// 开启循环渲染
engine.rendering.enableAnimationLoop = true;
我的发现:开启后,如果有动画效果(比如飞线、粒子等),会持续播放!
我的理解:默认情况下,引擎只在需要时渲染(比如拖动地图时)。开启循环渲染后,每帧都会渲染,适合有动画的场景。
尝试添加和移除物体
文档说可以用 engine.add 添加物体,用 engine.remove 移除物体:
// 添加物体
const point = engine.add(new mapvthree.SimplePoint());
const mesh = engine.add(new THREE.Mesh());// 移除物体
engine.remove(point);
engine.remove(mesh);
我的尝试:
// 创建一个点
const point = engine.add(new mapvthree.SimplePoint({size: 20,
}));
point.dataSource = dataSource;// 5 秒后移除
setTimeout(() => {engine.remove(point);console.log('点已移除');
}, 5000);
我的发现:5 秒后,点从地图上消失了!
我的感受:添加和移除都很简单,这样就能动态控制地图上的元素了!
第五天:完整示例
经过几天的学习,我想写一个完整的示例,把学到的都用上:
import * as mapvthree from '@baidumap/mapv-three';
import * as THREE from 'three';// 获取容器
const container = document.getElementById('container');// 创建引擎
const engine = new mapvthree.Engine(container, {map: {center: [116.404, 39.915], // 天安门range: 1000,heading: 0,pitch: 60,},rendering: {enableAnimationLoop: true, // 开启循环渲染},
});// 创建数据源(两个点)
const dataSource = new mapvthree.GeoJSONDataSource.fromGeoJSON({type: 'FeatureCollection',features: [{type: 'Feature',properties: { name: '点1' },geometry: {type: 'Point',coordinates: [116.404, 39.915],},},{type: 'Feature',properties: { name: '点2' },geometry: {type: 'Point',coordinates: [116.414, 39.925],},},],
});// 创建点图层
const point = engine.add(new mapvthree.SimplePoint({size: 30,
}));
point.dataSource = dataSource;// 添加点击事件
point.addEventListener('click', (e) => {const name = e.feature.properties.name;const coords = e.feature.geometry.coordinates;alert(`${name}\n经度:${coords[0]}\n纬度:${coords[1]}`);
});// 添加 3D 模型
const model = engine.add(new mapvthree.SimpleModel({name: 'building',point: [116.404, 39.915],url: 'assets/models/building/5_tiyuzhongxin.glb',
}));
我的感受:写一个完整的示例,把学到的都用上,感觉很有成就感!
我的发现:
- 地图可以正常显示
- 点数据可以正常显示
- 点击事件可以正常触发
- 3D 模型可以正常加载
虽然代码还很简单,但是已经能做出一个基本的 3D 地图应用了!
我的学习总结
经过这几天的学习,我掌握了:
-
安装和配置:
- 安装依赖包
- 配置静态资源
- 配置百度地图 AK
-
基础使用:
- 初始化引擎
- 配置地图参数
- 添加可视化组件
- 添加 3D 模型
- 添加交互事件
-
引擎属性:
engine.map:地图控制engine.rendering:渲染配置engine.add/engine.remove:添加/移除物体
我的感受:
- JSAPIThree 功能很强大,但是上手不难
- 文档很详细,按照文档一步步来就能学会
- 代码结构清晰,API 设计合理
- 能做出来的效果很酷炫!
我的下一步计划:
- 学习更多可视化组件(线、面、热力图等)
- 学习数据源的使用(CSV、JSON 等)
- 学习特效和动画
- 做一个完整的项目
我的建议:
- 初学者可以先从最简单的例子开始
- 多动手实践,看文档不如写代码
- 遇到问题先查文档,再查社区
- 不要怕出错,多试几次就会了
学习笔记就到这里啦!作为一个初学者,我觉得 JSAPIThree 虽然功能强大,但是学习曲线并不陡峭。只要按照文档一步步来,多动手实践,很快就能做出酷炫的 3D 地图效果!大家一起加油!