记录--写一个高德地图巡航功能的小DEMO
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
风格设置
加载地图
使用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);
镜头信息的获取
前文实例化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();
初始化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 轴.
旋转模型
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)
}
计算轨迹
使用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]]
// 导航线
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方法中,感兴趣的可以去 仓库 查看,
镜头跟踪
移动模型
利用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的基础知识,可以先提前了解一下,否则有很多好玩有趣的效果实现不出来。
其他
关于飞线,只是作为装饰,显得画面不那么呆板,在官网上也有案例,简单贴一个代码吧
// 飞线
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);
本文转载于:
https://juejin.cn/post/7242145254056673335
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

记录--写一个高德地图巡航功能的小DEMO的更多相关文章
- 写一个方法完成如下功能,判断从文本框textbox1输入的一个字符,如果是数字则求该数字的阶乘,如果是小写字条,则转换为大写,大写字符不变,结果在文本框textbox2中显示
		
窗体设计: 代码: using System; using System.Collections.Generic; using System.ComponentModel; using System. ...
 - 高德地图首席科学家任小枫QA答疑汇总丨视觉+地图技术有哪些新玩法?
		
上周,阿里巴巴高德地图首席科学家任小枫在#大咖学长云对话#的在线直播活动上就计算机视觉相关技术发展以及在地图出行领域的应用与大家做技术交流,直播间互动火爆,尤其在QA环节,学弟学妹们纷纷就感兴趣的视觉 ...
 - 写一个兼容性比较好的拖拽DEMO
		
写一个兼容性比较好的拖拽DEMO 查看Demo 思路 div盒子 鼠标按下事件onmousedown 鼠标移动事件onmousemove,获得鼠标的坐标,将div移动至鼠标的当前坐标 鼠标抬起事件om ...
 - 高德地图搜索功能以及清除搜索结果maker
		
第一次写文章,写得不好各位看官见谅~ (pσ_σ)P首先这是一个vue里面的项目,高德地图api是直接CDN进来的,所以使用了global来调用,默认已经初始化了一个地图,为了实现一个输入框搜索功能和 ...
 - C# GMap下提供一个高德地图
		
using System; using GMap.NET.Internals; using GMap.NET.Projections; namespace GMap.NET.MapProviders ...
 - wpf+xml实现的一个随机生成早晚餐的小demo
		
话说每到吃完的时间就发愁,真的不知道该吃什么,然后就想到做一个生成吃什么的小软件,既然这个软件如此的简单,就打算用wpf开发吧,也不用数据库了,直接保存在xml中就可以了 程序整体结构如下图 首先我写 ...
 - 一个基于ES6+webpack的vue小demo
		
上一篇文章<一个基于ES5的vue小demo>我们讲了如何用ES5,vue-router做一个小demo,接下来我们来把它变成基于ES6+webpack的demo. 一.环境搭建及代码转换 ...
 - 写一个JavaScript“返回顶部”功能
		
在web页面中,如果页面较高,为了方便用户快速地返回顶部,都会添加一个返回顶部按钮. 效果演示可以查看本页.如果页面有滚动高度,右下角就会有一个含有“返回顶部”字样的黑色背景半透明的小条条.点击这里“ ...
 - 使用python 写一个  股票涨跌提醒功能
		
1: 安装python: https://www.cnblogs.com/liyafei/articles/11550979.html 将python.exe加入 全局path 2: 安装库:(不需要 ...
 - 用Python写一个向数据库填充数据的小工具
		
一. 背景 公司又要做一个新项目,是一个合作型项目,我们公司出web展示服务,合作伙伴线下提供展示数据. 而且本次项目是数据统计展示为主要功能,并没有研发对应的数据接入接口,所有展示数据源均来自数据库 ...
 
随机推荐
- 二进制安装Kubernetes(k8s) v1.27.3 IPv4/IPv6双栈 可脱离互联网
			
二进制安装Kubernetes(k8s) v1.27.3 IPv4/IPv6双栈 可脱离互联网 https://github.com/cby-chen/Kubernetes 开源不易,帮忙点个star ...
 - JS leetcode 加一 题解分析
			
壹 ❀ 引 今天是刷leetcode的第三天,根据推荐优先刷数据结构相关的卡片,先把数据结构知识体系建立起来,不然就是题目无从下手答案也看不懂的尴尬局面.那么今天的题目是加一,老规矩,先记录自己的解题 ...
 - js 实现call和apply方法,超详细思路分析
			
壹 ❀ 引 我在 五种绑定策略彻底弄懂this 一文中,我们提到call,apply,bind属于显示绑定,这三个方法都能直接修改this指向.其中call与apply比较特殊,它们在修改this的同 ...
 - Codeforces Round #825 (Div. 2) A-D
			
比赛链接 A 题解 知识点:贪心. 考虑两种方法: 所有不同的位置使用操作1变成相同 使用操作1将两串01数量相同,然后使用1次操作2 取其中最小的即可. 时间复杂度 \(O(n)\) 空间复杂度 \ ...
 - Java集合篇之set,面试官:请说一说HashSet、LinkedHashSet、TreeSet的区别?
			
写在开头 Java的集合世界中主要由List,Set,Queue,Map构成,我们在之前的博文中已经学习了List,接下来我们继续学习Set集合. Set特点:存取无序,不可以存放重复的元素,不可以用 ...
 - 基于 junit5 实现 junitperf 源码分析
			
前言 上一节介绍了基于 junit4 实现 junitperf,但是可以发现定义变量的方式依然不够优雅. 那可以让用户使用起来更加自然一些吗? 有的,junit5 为我们带来了更加强大的功能. 拓展阅 ...
 - java zTree异步加载实战
			
zTree简介 zTree 是一个依靠 jQuery 实现的多功能 "树插件".优异的性能.灵活的配置.多种功能的组合是 zTree 最大优点. zTree 是开源免费的软件(MI ...
 - QT - Day 3
			
对话框 分类 模态对话框 QDialog dlg(this); dlg.resize(200,100); dlg.exec(); //窗口阻塞 非模态对话框 QDialog *dlg2 = new Q ...
 - [BUUCTF][Web][极客大挑战 2019]Havefun 1
			
打开靶机的URL,看到一个页面 右键查看源代码,看到有用信息 <html> ... <!-- $cat=$_GET['cat']; echo $cat; if($cat=='dog' ...
 - defaultdict高级用法
			
说明 defaultdict数据结构允许调用者提供一个函数,用来在键名缺失的情况下,创建与这个 键对应的值.只要字典发现调用者想要访问的键不存在,就会触发这个函数,以返回应该 与键相关联的默认值 下面 ...
 
			
		