基于cesium和高德地图API的路径规划

基于cesium和高德地图API的路径规划

cesium

  • 作为一个开源的、世界级的、展现3D全球地图的JavaScript类库,Cesium毫无疑问已然成为WebGIS开发中三维地球框架的首选,(https://cesium.com/)

  • cesium的组成和功能,如下表所示

Component Description
Viewer 提供3D、2D、2.5D的地图视图
DataSource 支持多种数据源,包括地形、影像、矢量数据等
Entity 用于在地图上展示点、线、面等几何图形
Widget 提供了一系列UI组件,如指南针、缩放控件等
Scene 管理和渲染3D场景
Camera 控制视角和视图
CesiumWidget 不带UI控件的Cesium Viewer的简化版本
Primitives 用于渲染几何图形和图像
ImageryLayer 管理地图影像图层
TerrainProvider 提供地形数据

高德地图api

  • 高德地图api在js中的应用,有两大类一种是已经封装好的web服务,一种是js API
类别 描述 使用场景
Web服务 高德地图提供的一系列服务器端API,可以通过HTTP请求访问。这些服务包括地理编码、路径规划、静态地图等。 当你需要在服务器端处理地图数据,或者在客户端进行简单的HTTP请求以获取地图数据时使用。
JavaScript API 一套在网页中直接嵌入和操作地图的接口。提供了丰富的功能,如地图显示、交互、覆盖物添加等。 当你需要在网页中嵌入交互式地图,实现复杂的地图操作和数据可视化时使用。

前者已经封装好api,直接访问即可返回数据,而后者是需要在前端页面中嵌入的地图功能。

输入提示(JS API)

安装

1
npm install @amap/amap-jsapi-loader

引入

ES Module:

1
2
3
4
5
6
7
8
9
10
11
12
import AMapLoader from '@amap/amap-jsapi-loader'
// 初始化地图时要配置key,和密钥
// 因为我没配置密钥导致我的提示一直不出来,搞了好久才成功
AMapLoader.load({
"key": "你的高德地图API密钥", // 请替换成你的高德地图API密钥
"version": "2.0", // API版本号
"plugins": [] // 需要使用的插件列表
}).then((AMap) => {
// 高德地图API已成功加载,现在可以通过AMap对象进行地图开发了
}).catch(e => {
console.log(e); // 加载错误
});
1
2
3
4
5
6
7
8
// 在index.html中通过CDN的方式引入
<script type="text/javascript">
window._AMapSecurityConfig = {
securityJsCode:'安全密钥',
}
</script>
<script src="https://webapi.amap.com/maps?v=2.0&key=我的key"></script>
<script src="https://webapi.amap.com/ui/1.1/main.js"></script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//使得id为inputId的input元素可以实现搜索提示
const initAutocomplete = (inputId) => {
// 延迟执行,确保DOM元素已经渲染
nextTick(() => {
AMap.plugin('AMap.AutoComplete', () => {
const autoOptions = {
input: inputId
};
const autoComplete = new AMap.Autocomplete(autoOptions);
//选中某个poi之后的操作,获取poi的经纬度用于后续路径规划
autoComplete.on('select', (e) => {
console.log('select', e)
if (inputId === 'tipinput1') {
startPoint.value = e.poi.name;
startCoor.value.lng = e.poi.location.lng;
startCoor.value.lat = e.poi.location.lat;
// startCity.value = e.poi.sdcode;
} else {
endPoint.value = e.poi.name;
endCoor.value.lng = e.poi.location.lng;
endCoor.value.lat = e.poi.location.lat;
// endCity.value = e.poi.adcode ;
}
});
});
});
};

路径规划(web 服务)

只需处理数据,把输入数据根据api要求拼接成想要url即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//封装好的axios
import instance from "./outServeRequest.js"
// 访问高德地图api,获取数据;v3有polyline,v5没有
const url = '/amap/v3/direction/'
const key = '我的key'
export function getRoute(routeOpt,originCoor,destinationCoor,) {
let routeUrl = ''
if (routeOpt === 'integrated') {
//后面两个city的值是城市的adcode
routeUrl = `${url}/transit/${routeOpt}?&key=${key}&origin=${originCoor.lng},${originCoor.lat}&destination=${destinationCoor.lng},${destinationCoor.lat}&city=110000&cityd=110000`
} else {
routeUrl = `${url}${routeOpt}?&key=${key}&origin=${originCoor.lng},${originCoor.lat}&destination=${destinationCoor.lng},${destinationCoor.lat}`
}
return routeUrl
}
// 发起get请求
export function getRouteData(routeOpt,originCoor,destinationCoor) {
const routeUrl = getRoute(routeOpt,originCoor,destinationCoor)
return instance.get(routeUrl)
}

使用api时常看控制台的网络服务,看看请求是否发送,响应是什么。如果发生错误可以根据响应代码对照高德地图api提供的错误代码查看错误类型()

前后端的跨域问题

后端跨域问题配置,只能解决后端提供的api

而第三方提供的api修改后端跨域无法解决,由于我用的打包工具时vite,在解决第三方跨域问题时需要配置vite.config.js,设置代理为'/amap'。配置之后前端api访问时的地址也需要更改需要使用代理,'/amap/v3/direction'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
vite.config.js
export default defineConfig({
server: {
proxy: {
// 代理所有到 /amap 的请求到 https://restapi.amap.com
'/amap': {
//第三方地址,这里用amap代理了,那么请求的地址就应该时amap开头
target: 'https://restapi.amap.com', // 目标地址
changeOrigin: true, // 必须设置为true,以便代理服务器发送请求时更改Origin头信息
rewrite: (path) => path.replace(/^\/amap/, ''), // 将请求地址中的 /amap 替换为空,因为实际的API地址中不包含 /amap
secure: false,
xfwd: true,
}
}
}
})
1
2
3
4
5
6
前端使用代理
const url = `/amap/v3/assistant/coordinate/convert?key=${key}&locations=${locations}&coordsys=gps`

不使用代理前的url为
'https://restapi.amap.com/v3/assistant/coordinate/...'

坐标系转换

高德地图的坐标系和cesium的坐标系是不同的,当然不同数据的坐标系都有差异,我们需要进行坐标系的转换。
可以借助现有的库,我用的是gcoord(https://github.com/hujiulong/gcoord)

安装

npm 安装

1
npm install gcoord --save

或者直接在页面中通过 script 标签引入:

1
<script src="https://unpkg.com/gcoord/dist/gcoord.global.prod.js"></script>

引入

CommonJS:

1
const gcoord = require('gcoord');

ES Module:

1
import gcoord from 'gcoord';

通过 script 标签引入可以直接使用全局变量 gcoord 或 window.gcoord

transform API

transform(input, from, to)

进行坐标转换

参数

  • input GeoJSON | string | Array GeoJSON对象,或GeoJSON字符串,或经纬度数组
  • from CRS 当前坐标系
  • to CRS 目标坐标系

返回值

GeoJSON | Array

示例

1
2
3
// 将GCJ02坐标转换为WGS84坐标
var result = gcoord.transform([123, 45], gcoord.GCJ02, gcoord.WGS84);
console.log(result); // [122.99395597, 44.99804071]
1
2
3
4
5
6
7
// 转换GeoJSON坐标
var geojson = {
"type": "Point",
"coordinates": [123, 45]
}
gcoord.transform(geojson, gcoord.GCJ02, gcoord.WGS84);
console.log(geojson.coordinates); // [122.99395597, 44.99804071]

返回数组或GeoJSON对象(由输入决定),注意:当输入为GeoJSON时,transform会改变输入对象

前一种输入为数组,后一种为一个geojson,geojson的coordinates可以是二维数组

CRS为坐标系,目标支持以下几种坐标系

CRS 坐标格式 说明
gcoord.WGS84 [lng,lat] WGS-84坐标系,GPS设备获取的经纬度坐标
gcoord.GCJ02 [lng,lat] GCJ-02坐标系,google中国地图、soso地图、aliyun地图、mapabc地图和高德地图所用的经纬度坐标
gcoord.BD09 [lng,lat] BD-09坐标系,百度地图采用的经纬度坐标
gcoord.BD09LL [lng,lat] 同BD09
gcoord.BD09MC [x,y] BD-09米制坐标,百度地图采用的米制坐标,单位:米
gcoord.BD09Meter [x,y] 同BD09MC
gcoord.Baidu [lng,lat] 百度坐标系,BD-09坐标系别名,同BD-09
gcoord.BMap [lng,lat] 百度地图,BD-09坐标系别名,同BD-09
gcoord.AMap [lng,lat] 高德地图,同GCJ-02
gcoord.WebMercator [x,y] Web Mercator投影,墨卡托投影,同EPSG3857,单位:米
gcoord.WGS1984 [lng,lat] WGS-84坐标系别名,同WGS-84
gcoord.EPSG4326 [lng,lat] WGS-84坐标系别名,同WGS-84
gcoord.EPSG3857 [x,y] Web Mercator投影,同WebMercator,单位:米
gcoord.EPSG900913 [x,y] Web Mercator投影,同WebMercator,单位:米

具体实现

踩坑总结