Mapbox gl HTML经纬度点渲染,动态轨迹播放,自定义图形以及轨迹上显示箭头方向

Mapbox gl HTML经纬度点渲染,动态轨迹播放,自定义图形以及轨迹上显示箭头方向

    • 1. 效果图
    • 2. 源码
      • 2.1 line.html
      • 2.2line_arrow.html
    • 参考

今天要排查个问题,需要显示多个经纬度点连接成线段的方向,于是尝试下展示。

1. mapbox渲染经纬度点,线,多线,面
2. 运动轨迹增加箭头方向
3. 增加一个图像(如小车等)本文用的tomcat小猫图标,实行运动轨迹可控制,开始,播放,停止

1. 效果图

线渲染:

在这里插入图片描述

点、线渲染:

在这里插入图片描述

增加箭头显示方向,以及tomcat小猫播放:

在这里插入图片描述
轨迹播放中截图:

在这里插入图片描述

在这里插入图片描述

增加轨迹方向箭头及小猫播放中截图如下:
在这里插入图片描述
修改地图背景色,实时轨迹线颜色,播放中截图如下:
在这里插入图片描述

2. 源码

2.1 line.html

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>Add a GeoJSON line</title><meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"><link href="https://api.mapbox.com/mapbox-gl-js/v2.1.1/mapbox-gl.css" rel="stylesheet"><script src="https://api.mapbox.com/mapbox-gl-js/v2.1.1/mapbox-gl.js"></script><style>body {margin: 0;padding: 0;}#map {position: absolute;top: 0;bottom: 0;width: 100%;}</style>
</head>
<body>
<div id="map"></div>
<script>// TO MAKE THE MAP APPEAR YOU MUST// ADD YOUR ACCESS TOKEN FROM// https://account.mapbox.commapboxgl.accessToken = 'pk.eyJ1******************Lc99g';var map = new mapboxgl.Map({container: 'map',style: 'mapbox://styles/mapbox/streets-v11',
// center: [-122.486052, 37.830348],
// center: [116.239749,40.0717456],
// center: [117.85448020099696,35.96263648233899],center: [116.25456103528076, 40.07649758667226],zoom: 14});map.on('load', function () {map.addSource('route', {'type': 'geojson','data': {'type': 'FeatureCollection','features': [{'type': 'Feature','properties': {},'geometry': {'type': 'LineString','coordinates': [[116.25456103528076, 40.07649758667226, 32.60466429684311],[116.25459033603693, 40.076511383622965, 32.46827581245452],[116.25455860845449, 40.07650334314173, 32.52390295546502],[116.25460283054188, 40.07651455000795, 32.44636987615377]]}},{'type': 'Feature','geometry': {'type': 'Point','coordinates': [116.25456103528076, 40.07649758667226, 32.60466429684311]}},{'type': 'Feature','geometry': {'type': 'Point','coordinates': [116.25459033603693, 40.076511383622965, 32.46827581245452]}},{'type': 'Feature','geometry': {'type': 'Point','coordinates': [116.25455860845449, 40.07650334314173, 32.52390295546502]}},{'type': 'Feature','geometry': {'type': 'Point','coordinates': [116.25460283054188, 40.07651455000795, 32.44636987615377]}}]}});map.addLayer({'id': 'route','type': 'line','source': 'route','layout': {'line-join': 'round','line-cap': 'round'},'paint': {'line-color': '#DC143C','line-width': 5}});map.addLayer({'id': 'routePoint','type': 'circle','source': 'route','paint': {'circle-radius': 6,'circle-color': '#0000FF'},'filter': ['==', '$type', 'Point']});});
</script></body>
</html>

2.2line_arrow.html

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>Add a GeoJSON line,with Arrow</title><meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"><link href="https://api.mapbox.com/mapbox-gl-js/v2.1.1/mapbox-gl.css" rel="stylesheet"><script src="https://api.mapbox.com/mapbox-gl-js/v2.1.1/mapbox-gl.js"></script><script src="https://unpkg.com/@turf/turf@6.3.0/turf.min.js"></script><style>body {margin: 0;padding: 0;}.menuBar {position: relative;top: 10px;margin: 0 50px;padding: 5px;border-radius: 3px;z-index: 999;background-color: rgba(0, 168, 0, 0.7);}input[type=button] {font-size: 16px;}#map {position: absolute;top: 0;bottom: 0;width: 100%;}/* 删除mapbox logo */.mapboxgl-ctrl {display: none !important;}</style>
</head><body>
<div id="map"></div>
<div class="menuBar"><input type="button" value="开始" onclick="startClick()"/><input type="button" value="暂停" onclick="pauseClick()"/><input type="button" value="停止" onclick="stopClick()"/><div id="canvas"></div>
</div>
<script>// TO MAKE THE MAP APPEAR YOU MUST ADD YOUR ACCESS TOKEN FROM// https://account.mapbox.commapboxgl.accessToken = 'pk.eyJ********';var map = new mapboxgl.Map({container: 'map',style: 'mapbox://styles/mapbox/streets-v11',// center: [116.25456103528076, 40.07649758667226],// zoom: 24center: [116.390619, 39.924317], // starting position [lng, lat]zoom: 13 // starting zoom});// 背景色// map.setStyle('mapbox://styles/mapbox/dark-v9');// 箭头-右var svgXML =`<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path d="M529.6128 512L239.9232 222.4128 384.7168 77.5168 819.2 512 384.7168 946.4832 239.9232 801.5872z" p-id="9085" fill="#ff00ff"></path></svg>`//给图片对象写入base64编码的svg流var svgBase64 = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(svgXML)));map.on('load', function () {let arrowIcon = new Image(20, 20)arrowIcon.src = svgBase64arrowIcon.onload = function () {map.addImage('arrowIcon', arrowIcon)console.log("----------1 " + arrowIcon)map.loadImage('img/arrowR.png', function (error, arrowIcon2) {if (arrowIcon2) {map.addImage('arrowIcon2', arrowIcon2);}})map.loadImage('img/car.png', function (error, carIcon) {if (carIcon) {console.log("----------2 " + arrowIcon)map.addImage('carIcon', carIcon);setRouteData()}console.log("----------3 " + arrowIcon)});}})var isPlay = falsevar counter = 0var steps = 0let aLength = 0;var routeGeoJson = {'type': 'FeatureCollection','features': [{'type': 'Feature','geometry': {'type': 'LineString','coordinates': [[116.391844, 39.898457],[116.377947, 39.898595],[116.368001, 39.898341],[116.357144, 39.898063],[116.351934, 39.899095],[116.35067, 39.905871],[116.3498, 39.922329],[116.349671, 39.931017],[116.349225, 39.939104],[116.34991, 39.942233],[116.366892, 39.947263],[116.387537, 39.947568],[116.401988, 39.947764],[116.410824, 39.947929],[116.42674, 39.947558],[116.427338, 39.9397],[116.427919, 39.932404],[116.428377, 39.923109],[116.429583, 39.907094],[116.41404, 39.906858],[116.405321, 39.906622],[116.394954, 39.906324],[116.391264, 39.906308],[116.390748, 39.916611]]/*[[116.25456103528076, 40.07649758667226, 32.60466429684311],[116.25459033603693, 40.076511383622965, 32.46827581245452],[116.25455860845449, 40.07650334314173, 32.52390295546502],[116.25460283054188, 40.07651455000795, 32.44636987615377]]*/}}]}var realRouteGeoJson = {'type': 'FeatureCollection','features': [{'type': 'Feature','geometry': {'type': 'LineString','coordinates': []}}]}var animatePointGeoJson = {'type': 'FeatureCollection','features': [{'type': 'Feature','properties': {},'geometry': {'type': 'Point','coordinates': []}}]}// 获取轨迹数据function setRouteData() {animatePointGeoJson.features[0].geometry.coordinates = routeGeoJson.features[0].geometry.coordinates[0]aLength = routeGeoJson.features[0].geometry.coordinates.length;newRouteGeoJson = resetRoute(routeGeoJson.features[0], 1000, 'kilometers')steps = newRouteGeoJson.geometry.coordinates.lengthaddRoutelayer() // 添加轨迹线图层addRealRouteSource() // 添加实时轨迹线图层addArrowlayer() // 添加箭头图层addAnimatePointSource() // 添加动态点图层}// 添加轨迹线图层function addRoutelayer() {map.addLayer({'id': 'routeLayer','type': 'line','source': {'type': 'geojson','lineMetrics': true,'data': routeGeoJson},'paint': {'line-width': 10,'line-opacity': 1,'line-color': '#009EFF',}});}// 添加实时轨迹线function addRealRouteSource() {map.addLayer({'id': 'realRouteLayer','type': 'line','source': {'type': 'geojson','lineMetrics': true,'data': realRouteGeoJson},'paint': {'line-width': 3,'line-opacity': 1,'line-color': '#FF0000',}});}// 添加箭头图层function addArrowlayer() {console.log("-------addArrowlayer")map.addLayer({'id': 'arrowLayer','type': 'symbol','source': {'type': 'geojson','data': routeGeoJson //轨迹geojson格式数据},'layout': {'symbol-placement': 'line','symbol-spacing': 50, // 图标间隔,默认为250'icon-image': 'arrowIcon2', //箭头图标'icon-size': 0.5,'icon-rotate': ['get', 'bearing'],'icon-rotation-alignment': 'map','icon-allow-overlap': true,'icon-ignore-placement': true}});console.log("-------addArrowlayer end...")}// 添加动态点图层function addAnimatePointSource() {map.addLayer({'id': 'animatePointLayer','type': 'symbol','source': {'type': 'geojson','data': animatePointGeoJson},'layout': {'icon-image': 'carIcon','icon-size': 0.5,'icon-rotate': ['get', 'bearing'],'icon-rotation-alignment': 'map','icon-allow-overlap': true,'icon-ignore-placement': true}});animate()}function animate() {if (counter >= steps) {return}var startPnt, endPntif (counter == 0) {realRouteGeoJson.features[0].geometry.coordinates = []startPnt = newRouteGeoJson.geometry.coordinates[counter]endPnt = newRouteGeoJson.geometry.coordinates[counter + 1]} else if (counter !== 0) {startPnt = newRouteGeoJson.geometry.coordinates[counter - 1]endPnt = newRouteGeoJson.geometry.coordinates[counter]}animatePointGeoJson.features[0].properties.bearing = turf.bearing(turf.point(startPnt),turf.point(endPnt)) - 90;animatePointGeoJson.features[0].geometry.coordinates = newRouteGeoJson.geometry.coordinates[counter];realRouteGeoJson.features[0].geometry.coordinates.push(animatePointGeoJson.features[0].geometry.coordinates)map.getSource('animatePointLayer').setData(animatePointGeoJson);map.getSource('realRouteLayer').setData(realRouteGeoJson);if (isPlay) {requestAnimationFrame(animate);}counter = counter + 1;}function resetRoute(route, nstep, units) {var newroute = {'type': 'Feature','geometry': {'type': 'LineString','coordinates': []}}var lineDistance = turf.lineDistance(route);var nDistance = lineDistance / nstep;for (let i = 0; i < aLength - 1; i++) {var from = turf.point(route.geometry.coordinates[i]);var to = turf.point(route.geometry.coordinates[i + 1]);let lDistance = turf.distance(from, to, {units: units});if (i == 0) {newroute.geometry.coordinates.push(route.geometry.coordinates[0])}if (lDistance > nDistance) {let rings = lineMore(from, to, lDistance, nDistance, units)newroute.geometry.coordinates = newroute.geometry.coordinates.concat(rings)} else {newroute.geometry.coordinates.push(route.geometry.coordinates[i + 1])}}return newroute}function lineMore(from, to, distance, splitLength, units) {var step = parseInt(distance / splitLength)var leftLength = distance - step * splitLengthvar rings = []var route = turf.lineString([from.geometry.coordinates, to.geometry.coordinates])for (let i = 1; i <= step; i++) {let nlength = i * splitLengthlet pnt = turf.along(route, nlength, {units: units});rings.push(pnt.geometry.coordinates)}if (leftLength > 0) {rings.push(to.geometry.coordinates)}return rings}function startClick() {if (!isPlay) {isPlay = trueanimate()}}function pauseClick() {isPlay = falseanimate()}function stopClick() {isPlay = falsecounter = 0animate()}
</script></body></html>

参考

  • https://www.mianshigee.com/note/detail/11900gfx/
  • https://github.com/gisarmory/gisarmory.blog/blob/master/mapboxgl-PolylineDecorator/demo.html

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

element plus封装el-select添加后缀图标并添加远程搜索和对话框功能

当提交的表单Form需要填某个实体的外键ID时&#xff0c;当然不可能使用el-input组件&#xff0c;这个适合提交字符串&#xff0c;然后用户又不可能记住某个引用的外键ID&#xff0c;这时候使用el-select还是必要的。 el-select组件一般都作为下拉选择框使用&#xff0c;但仅在…

远程计算机控制软件

远程控制软件允许您连接和控制位于不同位置的设备&#xff0c;对于 IT 帮助台技术人员来说&#xff0c;这是一个很好的工具&#xff0c;可以通过与用户协作、与他们聊天以及安全地访问他们的文件来轻松排除故障和修复远程设备。使用远程控制软件&#xff0c;距离不再是提供技术…

无涯教程-JavaScript - ATAN函数

描述 The ATAN function returns the arctangent, or inverse tangent, of a number. The returned angle is given in radians between -π/2 and π/2. The arctangent is the angle whose tangent is number. 语法 ATAN (number)争论 Argument描述Required/OptionalNumb…

Vulnhub实战-prime1

前言 VulnHub 是一个面向信息安全爱好者和专业人士的虚拟机&#xff08;VM&#xff09;漏洞测试平台。它提供了一系列特制的漏洞测试虚拟机镜像&#xff0c;供用户通过攻击和漏洞利用的练习来提升自己的安全技能。本次&#xff0c;我们本次测试的是prime1。 一、主机发现和端…

Jmeter性能实战之分布式压测

分布式执行原理 1、JMeter分布式测试时&#xff0c;选择其中一台作为调度机(master)&#xff0c;其它机器作为执行机(slave)。 2、执行时&#xff0c;master会把脚本发送到每台slave上&#xff0c;slave 拿到脚本后就开始执行&#xff0c;slave执行时不需要启动GUI&#xff0…

【机器学习】文本多分类

声明&#xff1a;这只是浅显的一个小试验&#xff0c;且借助了AI。使用的是jupyter notebook,所以代码是一块一块&#xff0c;从上往下执行的 知识点&#xff1a;正则删除除数字和字母外的所有字符、高频词云、混淆矩阵 参考&#xff1a;使用python和sklearn的中文文本多分类…

DS相关题目

DS相关题目 题目一&#xff1a;消失的数字 拿到这道题目之后&#xff0c;首先可以想到的一个解题方法就是&#xff0c;我们可以先排序&#xff0c;排完序之后&#xff0c;这个数组其实就是一个有序的数组了&#xff0c;那只用比较数组中的每一个元素和他对应的下标是不是相等的…

代码管理工具git1

ctrl 加滚轮 放大字体 在计算机任意位置单击右键&#xff0c;选择&#xff1a;&#xff1a;Git Bash Here git version git清屏命令&#xff1a;ctrl L查看用户名和邮箱地址&#xff1a; $ git config user.name$ git config user.email修改用户名和邮箱地址&#xff1a;$ git…

C#中Visual Studio如何为解决方案设置启动项目

目录 第一种方法:快速选定启动项目的方法1.在解决方案资源管理器中,选择解决方案(最高层节点)2.选择解决方案节点的上下文(右键单击)菜单,然后选择“属性”。 “解决方案属性页”对话框随即显示第二种方法:右击First11或者second11,点击设置启动项目即可Visual Studio…

C#使用DirectX SDK 加载.x三维模型

最近因为项目要做显示一个三维模型&#xff0c;所以研究了下如何在Winform中加载并显示三维模型。在Windows平台巨硬公司提供了DirectX SDK用于渲染图形&#xff0c;参考了几篇文章做了个demo记录下&#xff0c;以便日后温习只用。这个SDK涉及到了计算机图形学的一些基础知识&a…

【物联网】简要解释RTK(Real-Time Kinematic)>>实时动态差分定位

引言&#xff1a; RTK&#xff08;Real-Time Kinematic&#xff09;技术是一种基于差分GPS的高精度定位技术&#xff0c;它通过实时通信和数据处理&#xff0c;能够提供厘米级甚至亚米级的定位精度。RTK技术在许多领域都得到了广泛应用&#xff0c;如测绘、航空航天、农业等。本…

Springboot -- DOCX转PDF(二)

之前记录了按照模板生成 DOCX 文件、并转换为 PDF 文件的方法 https://blog.csdn.net/qq_40096897/article/details/131979177?spm1001.2014.3001.5501 但是使用效果并不是很理想&#xff0c;转换完的 PDF 格式和原本的文档格式不匹配。所以在此重新找了一个文件转 PDF 的方法…

职场工作与生活

序言&#xff1a; 和很多在CSDN的博主一样&#xff0c;大家在工作之后就很少或者是不再回到CSDN&#xff0c;确实自己也一年多没上了。因为可能当初大家在这就是为了记录和分享当初自己学习技术的东西。而大家走出象牙塔开始工作后&#xff0c;发生了很大的转变。在国内…

PY32F003F18之输入捕获

输入捕获是定时器的功能之一&#xff0c;配合外部引脚&#xff0c;捕获脉宽时间或采集周期。 CPU中的定时器最基本的功能就是计数功能&#xff0c;其次是输入捕获(IC)&#xff0c;再次就是比较输出(OC)&#xff0c;还有就是使用引脚对外部时钟进行计数&#xff0c;触发信号捕捉…

阿里云 linux 的nginx 配置uni-app的H5前端项目vue,后端接口阿里云。

背景 vue项目调用接口是阿里云的&#xff0c;H5网站也要部署到阿里云&#xff0c;2个不同的服务器&#xff0c;需要做nginx部署与api代理。 端口配置 首先当然是买个阿里云服务器&#xff0c;这里是配置是linux系统&#xff0c;配置访问的域名 &#xff0c;再接着&#xff1…

iOS系统暗黑模式

系统暗黑模式&#xff1a; 暗黑模式颜色适配&#xff1a; 方式1&#xff1a; Assets配置&#xff1a;在Assets中配置好颜色后&#xff0c;可以通过colorNamed: 放大获取到动态颜色。 方式2&#xff1a;代码配置&#xff0c;通过代码colorWithDynamicProvider: 可以看出来生成…

【Obsidian】中编辑模式和阅读模式光标乱跳问题以及编辑模式中段落聚集的问题解决

前言 最近用Obsidian 软件写md笔记&#xff0c;但是当我分别使用编辑模式和阅读模式时出现了光标乱跳的问题。比如我在编辑模式&#xff0c;光标停留在第500行&#xff0c;但是切换成编辑模式就变成了1000行。而且光标根本没停在原来的位置。这样重新定位非常麻烦。 两种阅读…

我眼中的大数据: 我们未来该往何处

满打满算&#xff0c;工作接近三年的时间了&#xff0c;入行大数据也三年了。从开始时惊艳于大数据处理的高效&#xff0c;到现在时常迷茫未来数据的出路在哪&#xff0c;恍恍惚惚跨过了互联网的高峰。今天突然觉得&#xff0c;该总结下过去&#xff0c;思考下未来。我尽可能少…

自动化控制系统的设计重点是什么?

要实现对选择性激光烧结系统预热温度的控制&#xff0c;需要找到合理的控制对象模型&#xff0c;但选择性激光烧结设备的预热温度场是一个复杂的非线性系统&#xff0c;很难找到合理的控制对象模型来实现预热温度场的温度控制。模糊控制不需要具体的控制模型&#xff0c;预热温…

3ds max文件打包?max插件CG Magic一键打包整起!

3ds max文件如何打包&#xff1f;这个问题&#xff0c;小编听到不少网友的提问&#xff01; 今天CG Magic小编来和大家聊聊&#xff0c;文件更高效的操作&#xff0c;如何打包处理呢&#xff1f; 3DMAX这款软件的受众群体是比较高的&#xff0c;在工作方便的同时&#xff0c;…