【GIS开发小课堂】写一个高德地图巡航功能的小DEMO

介绍

此项目使用vite为基础架构,内部实现均以typescript开发,可替换为自己的业务逻辑,并迁移到reactvueumi等其他框架。

通过调用高德地图的API和threejs的开发,实现了一个小鸭子(可替换为自己的模型)沿着规划路线行走,并使镜头跟随小鸭子前进的功能。

该功能主要常见于外卖平台的骑手、滴滴司机、以及情侣软件的实时共享位置。

实现思路

1.加载地图

使用AMapLoader.load加载地图,从高德开放平台控制台申请一个属于自己的key
import AMapLoader from '@amap/amap-jsapi-loader';...
const AMap = await AMapLoader.load({  
"key": "您自己申请的KEY",   // 申请好的Web端开发者Key,首次调用 load 时必填    
"version": "2.0",    
"plugins": ["AMap.Walking", "AMap.Driving"],    // 需要使用的的插件列表,如比例尺'AMap.Scale'等    
"Loca": { version: '2.0.0'   }
})

使用new AMap.Map实例化地图,并设置mapStyle"amap://styles/grey",也可以在官网上自己设计属于自己的风格,主要讲的不是这部分所以大概交代一下就过去了,实例化Map后返回一个map实例,后续的操作都需要用到。

添加GLCustomLayer图层
new AMap.GLCustomLayer({    zIndex: 100,    init:()=>{},    render: ()=>{}})

threejs的加载和创建需要在init属性的方法里操作,render主要是用来渲染一些镜头信息和 WebGLRenderer的重绘。

在init方法中创建一个THREEJS的透视相机。

camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 100, 1 << 30);

2.镜头信息的获取

前文实例化Map后获取一个map的实例,其中提供了customCoords数据转换的工具,可以从这里获取到镜头信息,后续转化经纬度到3D世界坐标时候也会用到,转换工具需要提前获取到,方便后续的工作。

var { near, far, fov, up, lookAt, position } = customCoords.getCameraParams();

转换工具提供一个getCameraParams方法,其中包含相机位置等其他属性。


fov — 摄像机视锥体垂直视野角度
near — 摄像机视锥体近端面
far — 摄像机视锥体远端面


其中大部分属性都和threejs的透视相机属性相同,在render方法中更新相机,这样做的作用就是在后续做巡航功能时会实时更新相机位置。

camera.near = near;camera.far = far;camera.fov = fov;camera.position.set(...position);camera.up.set(...up);camera.lookAt(...lookAt);camera.updateProjectionMatrix();

3.初始化loca

可视化图层需要用到Loca容器,需要在地图外绘制的图层,需要在可视化图层上绘制。

创建可视化作品前,首先要创建一个 Loca 容器,这个容器可以帮您加载高德地图作为底图,或者帮您关联已有的高德地图作为底图。


在使用地图的时,您可以使用任何一个 JS API 已有的功能,Loca 容器不会影响原有地图的任何功能和特性。这里创建的 Loca 容器您可以理解为是可视化图层的管理器。

注意:创建地图时候 Loca 版本要和map的版本一致,否则会报错。​​​​​​​

var loca = new (window as any).Loca.Container({    map,    zIndex: 9});

将创建好的AMap.GLCustomLayer添加到map图层。​​​​​​​

    const customLayer = await createGLCustomLayer(AMap, customCoords)    map.add(customLayer);

createGLCustomLayer方法就是之前定义的初始化AMap.GLCustomLayer方法。

返回一个GLCustomLayer实例,这样就可以在地图内插入可视化内容。

加载模型

回到new AMap.GLCustomLayer提供的init属性中,创建一个3d场景并把模型加载到场景中。​​​​​​​

renderer = new THREE.WebGLRenderer({    context: gl,  // 地图的 gl 上下文});
// 自动清空画布这里必须设置为 false,否则地图底图将无法显示renderer.autoClear = false;
scene = new THREE.Scene();

加载模型方法跟threejs相同,使用gltfloderapi,加载方法返回一个promise,再使用。​​​​​​​​​​​​​​

// 初始化模型function initGltf(): Promise<THREE.Object3D> {    return new Promise((resolve, reject) => {        var loader = new GLTFLoader();        loader.load('https://a.amap.com/jsapi_demos/static/gltf/Duck.gltf', (gltf: any) => {            let object = gltf.scene;            resolve(object)        });    })}

模型添加到场景。​​​​​​​

const { x, y, z } = setRotation(new THREE.Vector3(90, 90, 0))
object.scale.set(15, 15, 15);group.add(object)group.add(new THREE.AxesHelper(100))scene.add(group)object.name = 'duck'

图片

我在模型上添加了一个AxesHelper辅助线,官网上表示蓝色代表z轴,但是放在地图中发生了坐标方向不一致的问题,threejs的向上方向是y轴,地图中z是向上方向,这一点可能要注意一下了。

用于简单模拟3个坐标轴的对象。
红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴。

4.旋转模型​​​​​​​

const { x, y, z } = setRotation(new THREE.Vector3(90, -90, 0))group.rotation.set(x, y, z)

获取旋转角度的方法。​​​​​​​

export function setRotation(rotation: THREE.Vector3) {    var x = Math.PI / 180 * (rotation.x || 0);    var y = Math.PI / 180 * (rotation.y || 0);    var z = Math.PI / 180 * (rotation.z || 0);    return new THREE.Vector3(x, y, z)}

图片

5.计算轨迹

使用viewControl

现在模型已经加载好,接下来就是要获取轨迹数据,镜头跟踪在Loca中有相应的apiviewControl,使用这个api调用addTrackAnimate方法,提供对应参数即可。

loca.viewControl.addTrackAnimate({    path: pathArr, // 镜头轨迹,二维数组,支持海拔    duration: 120000, // 时长    timing: [[0, 0.3], [1, 0.7]], // 速率控制器    rotationSpeed: 1800, // 每秒旋转多少度}, function () {    console.log('完成',);});

pathArr是一个轨迹数组。

const pathArr = [[116.310348, 39.89702], [116.310541, 39.884855], [116.320963, 39.889154], [116.322894, 39.889608], [116.325542, 39.889822], [116.328074, 39.889761], [116.349104, 39.889429], [116.348517, 39.89747], [116.355205, 39.898413], [116.35656, 39.90021], [116.355802, 39.93225]]

为了方便查看,我们在使用Loca提供的绘制引导线功能将这几个关键点连接的引导线画一下。​​​​​​​

// 导航线var polyline = new AMap.Polyline({    path: pathArr,            // 设置线覆盖物路径    showDir: true,    strokeColor: '#3366bb',   // 线颜色    strokeWeight: 10,           // 线宽    zIndex: 1});map.add(polyline)

以上工作做完后,需要调用一下loca.animate.start();方法,否则可视化图层不会更新,相应数据也获取不到,现在画面变成这样。

图片

除了以上这种方法去实现镜头的移动,还可以通过插入坐标的方式去实现,也是传统threejs中使用的方法,就是利用tweenjs的动画,运动过程中改变map.setCenter,实现跟踪,这部分代码在changeObject方法中。

6.镜头跟踪

移动模型

利用requestAnimationFrame函数写一个循环渲染的方法,在调用的同时获取镜头中心坐标,通过customCoords转换工具将经纬度转为3D世界的坐标,并将该坐标赋值给object模型,再通过map提供的getRotation方法,获取地图的旋转角度,并将该角度赋值给object模型的y轴,使模型沿着y轴旋转,至于旋转的速度,在前面定义addTrackAnimate时的rotationSpeed属性定义的。​​​​​​​

const render = () => {    requestAnimationFrame(() => {        render()    })    if (object) {        const center = map.getCenter()        var position = customCoords.lngLatsToCoords([            [center.lng, center.lat]        ])[0];        const v3 = new THREE.Vector3(position[1], 0, position[0])        object.position.copy(v3)        const rotation = map.getRotation()
        object.rotation.y = rotation * Math.PI / 180    }    map.render();    TWEEN && TWEEN.update()}

以上文章内容有一些关于threejs的基础知识,可以先提前了解一下,否则有很多好玩有趣的效果实现不出来。

图片

7.其他

关于飞线,只是作为装饰,显得画面不那么呆板,在官网上也有案例,简单贴一个代码吧。

 // 飞线var geo = new (window as any).Loca.GeoJSONSource({    url: 'https://a.amap.com/Loca/static/loca-v2/demos/mock_data/bj_bus.json',});
var layer = new (window as any).Loca.PulseLineLayer({    // loca,    zIndex: 10,    opacity: 1,    visible: true,    zooms: [1, 30],});
var headColors = ['#EFBB51', '#7F3CFF', '#4CC19B', '#0B5D74', '#E06AC4', '#223F9B', '#F15C1A', '#7A0FA6'];
layer.setSource(geo);
layer.setStyle({    altitude: 0,    lineWidth: 2,    // 脉冲头颜色    headColor: (_, feature) => {        return headColors[feature.properties.type - 1];    },    // 脉冲尾颜色    trailColor: 'rgba(128, 128, 128, 0.5)',    // 脉冲长度,0.25 表示一段脉冲占整条路的 1/4    interval: 0.25,    // 脉冲线的速度,几秒钟跑完整段路,可以通过计算距离动态改变时间    duration: 5000,});// 飞线结束
loca.add(layer);

three.js的版权声明及许可证:​​​​​​​

The MIT License
Copyright © 2010-2024 three.js authors
Permission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included inall copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE.

tween.js的版权声明及许可证:​​​​​​​

The MIT License
Copyright (c) 2010-2012 Tween.js authors.
Easing equations Copyright (c) 2001 Robert Penner http://robertpenner.com/easing/
Permission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included inall copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE.

相关源码和模型的下载链接地址

https://www.aspiringcode.com/content?id=17086628146313&uid=a8012550ef80420fa58669250592734c

本文由高德开放平台用户—孙华鹏提供

仅代表作者个人观点

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1534308.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

TiDB 扩容过程中 PD 生成调度的原理及常见问题丨TiDB 扩缩容指南(一)

导读 作为一个分布式数据库&#xff0c;扩缩容是 TiDB 集群最常见的运维操作之一。本系列文章&#xff0c;我们将基于 v7.5.0 具体介绍扩缩容操作的具体原理、相关配置及常见问题的排查。 通常&#xff0c;我们根据当前资源状态来决定是否需要调整 TiKV 节点的规模&#xff0…

Version ‘18.19.0‘ not found - try `nvm ls-remote` to browse available versions.

nvm安装指定版本不好使了 使用 nvm install 18.19.0 一直报错 Version 18.19.0 not found - try nvm ls-remote to browse available versions.然而使用 nvm ls-remote 只看到 iojs-v1.0.0iojs-v1.0.1iojs-v1.0.2iojs-v1.0.3iojs-v1.0.4iojs-v1.1.0iojs-v1.2.0iojs-v1.3.0iojs…

Wildberries测评自养号支付下单技术

Wildberries&#xff08;俄语&#xff1a;ООО Ягодки&#xff09;是俄罗斯最大的在线零售商&#xff0c;由Tatyana Bakalchuk于 2004 年创立。除俄罗斯外&#xff0c;他们还在其他 15 个国家提供服务&#xff1a;亚美尼亚、白俄罗斯、法国、德国、以色列、意大利、哈萨…

PHP省时省力海报在线制作系统小程序源码

省时省力海报在线制作系统&#xff1a;设计小白也能秒变大师 &#x1f3a8; 开篇&#xff1a;告别繁琐&#xff0c;拥抱高效设计 你还在为设计一张海报而熬夜加班吗&#xff1f;还在为找不到合适的素材而焦头烂额吗&#xff1f;别担心&#xff0c;“省时省力海报在线制作系统”…

使用开源框架HandyControl

准备 NuGet 搜索安装 HandyControl。 在App.xaml中添加以下代码&#xff1a; <Application.Resources><ResourceDictionary><ResourceDictionary.MergedDictionaries><ResourceDictionary Source"pack://application:,,,/HandyControl;component/…

大雪纷飞的视频素材去哪里找啊?雪景素材库分享

当冬季的银装素裹覆盖大地&#xff0c;无数抖音创作者便开始寻找那些可以捕捉到大雪纷飞的壮观画面。无论是为了制作节日主题的视频、记录下雪天的活动&#xff0c;还是单纯展示雪的清新美&#xff0c;优质的大雪视频素材都显得尤为重要。如果你正为寻找这类素材而苦恼&#xf…

建造者模式:灵活构建复杂对象的利器

在软件开发中&#xff0c;创建一个复杂对象通常需要多个步骤和参数&#xff0c;直接在客户端代码中进行这些操作不仅繁琐&#xff0c;而且难以维护。建造者模式&#xff08;Builder Pattern&#xff09;提供了一种优雅的解决方案&#xff0c;使得对象的创建过程更加清晰、灵活和…

磁盘写操作压力测试工具的设计与实现

磁盘写操作压力测试工具的设计与实现 1. 设计概述2. 关键技术点3. 伪代码设计4. C代码实现5. 运行与测试6. 结论在进行磁盘性能评估时,写操作压力测试是不可或缺的一部分。本篇文章将介绍如何使用C语言结合系统调用,设计并实现一个针对磁盘写操作的压力测试工具。这个工具将模…

LINUX网络编程:http

目录 1.认识http请求的字段 2.HTTP请求类 3.认识HTTP应答字段 4.HTTP应答类 5.源代码 协议就是一种约定&#xff0c;http也并不例外&#xff0c;使用http也无非就是&#xff0c;定义一个http请求的结构体&#xff0c;将结构体序列化为字符串&#xff0c;发送给服务器&…

2024年06月中国电子学会青少年软件编程(图形化)等级考试试卷(一级)答案 + 解析

青少年软件编程&#xff08;图形化&#xff09;等级考试试卷&#xff08;一级&#xff09; 分数&#xff1a;100 题数&#xff1a;37 一、单选题 音乐Video Game1的时长将近8秒&#xff0c;点击一次角色&#xff0c;下列哪个程序不能完整地播放音乐两次&#xff1f;&#xff0…

【Hot100】LeetCode—169. 多数元素

目录 1- 思路题目识别技巧 2- 实现⭐136. 只出现一次的数字——题解思路 3- ACM 实现 原题链接&#xff1a;169. 多数元素 1- 思路 题目识别 识别1 &#xff1a;统计数组中出现数量多余 [n/2] 的元素 技巧 值相同&#xff0c;则对 count 1&#xff0c;如果不相同则对值进行…

【C#】VS插件

翻译 目前推荐较多的 可以单词发言&#xff0c;目前还在开发阶段 TranslateIntoChinese - Visual Studio Marketplace 下载量最高的(推荐) Visual-Studio-Translator - Visual Studio Marketplace 支持翻译的版本较多&#xff0c;在 Visual Studio 代码编辑器中通过 Googl…

vue使用TreeSelect设置带所有父级节点的回显

Element Plus的el-tree-select组件 思路&#xff1a; 选中节点时&#xff0c;给选中的节点赋值 pathLabel&#xff0c;pathLabel 为函数生成的节点名字拼接&#xff0c;数据源中不包含。 在el-tree-select组件中设置 props“{ label: ‘pathLabel’ }” 控制选中时input框中回…

【信创】推荐一款好用的免费在线流程图思维导图工具 _ 统信 _ 麒麟 _ 方德

原文链接&#xff1a;【信创】推荐一款好用的免费在线流程图思维导图工具 | 统信 | 麒麟 | 方德 Hello&#xff0c;大家好啊&#xff01;今天给大家推荐一款非常好用的免费在线流程图和思维导图工具——ProcessOn。无论是项目管理、数据分析、头脑风暴还是日常办公&#xff0c;…

RFID读写器:零部件加工中的高效识别与管理利器

RFID读写器&#xff1a;零部件加工中的高效识别与管理利器 在传统零部件加工行业&#xff0c;面临着提高生产效率、保证生产计划执行、系统化管控产品质量以及有效管理库存等多方面的挑战&#xff0c;而 RFID 读写器在应对这些挑战的过程中扮演着至关重要的角色。 传统识别方式…

健身管理|基于java的健身管理系统小程序(源码+数据库+文档)

健身管理系统|健身管理系统小程序 目录 基于java的健身管理系统小程序 一、前言 二、系统设计 三、系统功能设计 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布道师&…

内幕!smardaten无代码平台全方位测评,这些细节你绝对想不到!

目录 一、引言二、测评要点2.1、前后端交互嵌套2.2、兼容性与可扩展性2.2.1、页面集成2.2.2、数据集成2.2.3、接口集成2.2.4、权限集成2.2.5、代码扩展支持 2.3、UI定制2.4、开发环境的隔离2.5、OEM定制2.6、多语言切换2.7、AI大模型能力 三、总结 一、引言 作为一枚IT从业者&…

Mega Stamp Bundle 地形合集捆绑包峡谷沙丘山脉

终极套装,满足所有地形雕刻需求! 自2015年Gaia发布以来,我们团队就发明了印章技术,欢迎来到Mega Stamp Bundle! 本套装包含14个印章包,单次购买即可享受大幅折扣,共获得140个专业设计的印章。 这些印章可与Unity Terrain Tools、Gaia以及任何使用印章高度图图像的工具…

memcmp函数的使用

目录 1.头文件 2.memcmp函数讲解 小心&#xff01;VS2022不可直接接触&#xff0c;否则&#xff01;没这个必要&#xff0c;方源面色淡然一把抓住&#xff01;顷刻炼化&#xff01; 1.头文件 memcmp函数的使用需要包括头文件 #include<string.h> 2.memcmp函数讲解 简述…

HTTPS原理详解

学习记录&#xff0c;仅供参考&#xff01; 一、HTTPS和HTTP的区别 二、HTTP的工作流程 三、实现原理 四、应用 01.准备工作 在客户端&#xff08;Windows&#xff09;生成证书&#xff0c;然后安装到服务端&#xff08;Linux&#xff09;。 安装OpenSSL工具 OpenSSL中包含…