首页IT科技vue的openlayers使用教程(vue利用openlayers实现动态轨迹)

vue的openlayers使用教程(vue利用openlayers实现动态轨迹)

时间2025-05-05 00:08:21分类IT科技浏览3257
导读:实现效果 今天介绍一个有趣的gis小功能:动态轨迹播放!效果就像这样:...

实现效果

今天介绍一个有趣的gis小功能:动态轨迹播放!效果就像这样:

这效果看着还很丝滑!别急            ,接下来教你怎么实现            。代码示例基于parcel打包工具和es6语法               ,本文假设你已经掌握相关知识和技巧               。

gis初学者可能对openlayers(后面简称ol)不熟悉      ,这里暂时不介绍ol了         ,直接上代码               ,先体验下感觉      。

创建一个地图容器

引入地图相关对象

import Map from ol/Map; import View from ol/View; import XYZ from ol/source/XYZ; import {Tile as TileLayer, Vector as VectorLayer} from ol/layer;

创建地图对象

const center = [-5639523.95, -3501274.52]; const map = new Map({ target: document.getElementById(map), view: new View({ center: center, zoom: 10, minZoom: 2, maxZoom: 19, }), layers: [ new TileLayer({ source: new XYZ({ attributions: attributions, url: ?key= + key, tileSize: 512, }), }), ], });

创建一条线路

画一条线路

可以用这个geojson网站随意画一条线         ,然后把数据内容复制下来      ,保存为json文件格式               ,作为图层数据添加到地图容器中         。

你可以用异步加载的方式           ,也可以用require方式   ,这里都介绍下吧:

// fetch fetch(data/route.json).then(function (response) { response.json().then(function (result) { const polyline = result.routes[0].geometry; }), }; // require var roadData = require(data/route.json)

后面基本一样了                ,就以fetch为准             ,现在把线路加载的剩余部分补充完整:

fetch(data/route.json).then(function (response) { response.json().then(function (result) { const polyline = result.routes[0].geometry; // 线路数据坐标系转换 const route = new Polyline({ factor: 1e6, }).readGeometry(polyline, { dataProjection: EPSG:4326, featureProjection: EPSG:3857, }); // 线路图层要素 const routeFeature = new Feature({ type: route, geometry: route, }); // 起点要素 const startMarker = new Feature({ type: icon, geometry: new Point(route.getFirstCoordinate()), }); // 终点要素 const endMarker = new Feature({ type: icon, geometry: new Point(route.getLastCoordinate()), }); // 取起点值 const position = startMarker.getGeometry().clone(); // 游标要素 const geoMarker = new Feature({ type: geoMarker, geometry: position, }); // 样式组合 const styles = { // 路线 route: new Style({ stroke: new Stroke({ width: 6, color: [237, 212, 0, 0.8], }), }), icon: new Style({ image: new Icon({ anchor: [0.5, 1], src: data/icon.png, }), }), geoMarker: new Style({ image: new CircleStyle({ radius: 7, fill: new Fill({color: black}), stroke: new Stroke({ color: white, width: 2, }), }), }), }; // 创建图层并添加以上要素集合 const vectorLayer = new VectorLayer({ source: new VectorSource({ features: [routeFeature, geoMarker, startMarker, endMarker], }), style: function (feature) { return styles[feature.get(type)]; }, }); // 在地图容器中添加图层 map.addLayer(vectorLayer);

以上代码很完整,我加了注释              ,整体思路总结如下:

先加载路线数据 构造路线          、起始点及游标对应图层要素对象 构造图层并把要素添加进去 在地图容器中添加图层

添加起                  、终点

这个上面的代码已经包括了               ,我这里列出来是为了让你更清晰   ,就是startMarker和endMarker对应的代码               。

添加小车

同样的            ,这里的代码在上面也写过了               ,就是geoMarker所对应的代码         。

准备开车

线路有了      ,车也有了         ,现在就到了激动人心的开车时刻了               ,接下来才是本文最核心的代码!

const speedInput = document.getElementById(speed); const startButton = document.getElementById(start-animation); let animating = false; let distance = 0; let lastTime; function moveFeature(event) { const speed = Number(speedInput.value); // 获取当前渲染帧状态时刻 const time = event.frameState.time; // 渲染时刻减去开始播放轨迹的时间 const elapsedTime = time - lastTime; // 求得距离比 distance = (distance + (speed * elapsedTime) / 1e6) % 2; // 刷新上一时刻 lastTime = time; // 反减可实现反向运动         ,获取坐标点 const currentCoordinate = route.getCoordinateAt( distance > 1 ? 2 - distance : distance ); position.setCoordinates(currentCoordinate); // 获取渲染图层的画布 const vectorContext = getVectorContext(event); vectorContext.setStyle(styles.geoMarker); vectorContext.drawGeometry(position); map.render(); } function startAnimation() { animating = true; lastTime = Date.now(); startButton.textContent = Stop Animation; vectorLayer.on(postrender, moveFeature); // 隐藏小车前一刻位置同时触发事件 geoMarker.setGeometry(null); } function stopAnimation() { animating = false; startButton.textContent = 开车了; // 将小车固定在当前位置 geoMarker.setGeometry(position); vectorLayer.un(postrender, moveFeature); } startButton.addEventListener(click, function () { if (animating) { stopAnimation(); } else { startAnimation(); } });

简单说下它的原理就是利用postrender事件触发一个函数      ,这个事件本来是地图渲染结束事件               ,但是它的回调函数中           ,小车的坐标位置一直在变   ,那就会不停地触发地图渲染                ,当然最终也会触发postrender      。这样就实现的小车沿着轨迹的动画效果了               。这段代码有点难理解             ,最好自己尝试体验下,比较难理解部分我都加上了注释           。

好了              ,ol动态巡查已经介绍完了               ,动手试下吧!看你的车能否开起来?

完整代码

index.html

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Marker Animation</title> <!-- Pointer events polyfill for old browsers, see https://caniuse.com/#feat=pointer --> <script src="https://unpkg.com/elm-pep"></script> <style> .map { width: 100%; height:400px; } </style> </head> <body> <div id="map" class="map"></div> <label for="speed"> speed: <input id="speed" type="range" min="10" max="999" step="10" value="60"> </label> <button id="start-animation">Start Animation</button> <script src="https://www.jb51.net/article/main.js"></script> </body> </html>

main.js

import ol/ol.css; import Feature from ol/Feature; import Map from ol/Map; import Point from ol/geom/Point; import Polyline from ol/format/Polyline; import VectorSource from ol/source/Vector; import View from ol/View; import XYZ from ol/source/XYZ; import { Circle as CircleStyle, Fill, Icon, Stroke, Style, } from ol/style; import {Tile as TileLayer, Vector as VectorLayer} from ol/layer; import {getVectorContext} from ol/render; const key = Get your own API key at https://www.maptiler.com/cloud/; const attributions = <a href="https://www.maptiler.com/copyright/" rel="external nofollow" target="_blank">&copy; MapTiler</a> + <a href="https://www.openstreetmap.org/copyright" rel="external nofollow" target="_blank">&copy; OpenStreetMap contributors</a>; const center = [-5639523.95, -3501274.52]; const map = new Map({ target: document.getElementById(map), view: new View({ center: center, zoom: 10, minZoom: 2, maxZoom: 19, }), layers: [ new TileLayer({ source: new XYZ({ attributions: attributions, url: ?key= + key, tileSize: 512, }), }), ], }); // The polyline string is read from a JSON similiar to those returned // by directions APIs such as Openrouteservice and Mapbox. fetch(data/polyline/route.json).then(function (response) { response.json().then(function (result) { const polyline = result.routes[0].geometry; const route = new Polyline({ factor: 1e6, }).readGeometry(polyline, { dataProjection: EPSG:4326, featureProjection: EPSG:3857, }); const routeFeature = new Feature({ type: route, geometry: route, }); const startMarker = new Feature({ type: icon, geometry: new Point(route.getFirstCoordinate()), }); const endMarker = new Feature({ type: icon, geometry: new Point(route.getLastCoordinate()), }); const position = startMarker.getGeometry().clone(); const geoMarker = new Feature({ type: geoMarker, geometry: position, }); const styles = { route: new Style({ stroke: new Stroke({ width: 6, color: [237, 212, 0, 0.8], }), }), icon: new Style({ image: new Icon({ anchor: [0.5, 1], src: data/icon.png, }), }), geoMarker: new Style({ image: new CircleStyle({ radius: 7, fill: new Fill({color: black}), stroke: new Stroke({ color: white, width: 2, }), }), }), }; const vectorLayer = new VectorLayer({ source: new VectorSource({ features: [routeFeature, geoMarker, startMarker, endMarker], }), style: function (feature) { return styles[feature.get(type)]; }, }); map.addLayer(vectorLayer); const speedInput = document.getElementById(speed); const startButton = document.getElementById(start-animation); let animating = false; let distance = 0; let lastTime; function moveFeature(event) { const speed = Number(speedInput.value); const time = event.frameState.time; const elapsedTime = time - lastTime; distance = (distance + (speed * elapsedTime) / 1e6) % 2; lastTime = time; const currentCoordinate = route.getCoordinateAt( distance > 1 ? 2 - distance : distance ); position.setCoordinates(currentCoordinate); const vectorContext = getVectorContext(event); vectorContext.setStyle(styles.geoMarker); vectorContext.drawGeometry(position); // tell OpenLayers to continue the postrender animation map.render(); } function startAnimation() { animating = true; lastTime = Date.now(); startButton.textContent = Stop Animation; vectorLayer.on(postrender, moveFeature); geoMarker.setGeometry(null); } function stopAnimation() { animating = false; startButton.textContent = 开车了; geoMarker.setGeometry(position); vectorLayer.un(postrender, moveFeature); } startButton.addEventListener(click, function () { if (animating) { stopAnimation(); } else { startAnimation(); } }); }); });

package.json

{ "name": "feature-move-animation", "dependencies": { "ol": "6.9.0" }, "devDependencies": { "parcel": "^2.0.0-beta.1" }, "scripts": { "start": "parcel index.html", "build": "parcel build --public-url . index.html" } }

参考资源:

https://openlayers.org/en/latest/examples/feature-move-animation.html

以上就是vue利用openlayers实现动态轨迹的详细内容   ,更多关于vue openlayers动态轨迹的资料请关注本站其它相关文章!

声明:本站所有文章            ,如无特殊说明或标注               ,均为本站原创发布   。任何个人或组织      ,在未征得本站同意时         ,禁止复制     、盗用       、采集                  、发布本站内容到任何网站        、书籍等各类媒体平台                。如若本站内容侵犯了原著者的合法权益               ,可联系我们进行处理             。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
python读取一个文件(python如何读取不同格式文件)