iis服务器助手广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >vue利用openlayers实现动态轨迹
  • 911
分享到

vue利用openlayers实现动态轨迹

vue openlayers动态轨迹vue openlayers 2022-11-13 19:11:09 911人浏览 薄情痞子
摘要

目录实现效果创建一个地图容器引入地图相关对象创建地图对象创建一条线路画一条线路添加起、终点添加小车准备开车完整代码实现效果 今天介绍一个有趣的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: 'https://api.maptiler.com/maps/hybrid/{z}/{x}/{y}.jpg?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);

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

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

添加起、终点

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

添加小车

同样的,这里的代码在上面也写过了,就是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="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: 'https://api.maptiler.com/maps/hybrid/{z}/{x}/{y}.jpg?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动态轨迹的资料请关注编程网其它相关文章!

--结束END--

本文标题: vue利用openlayers实现动态轨迹

本文链接: https://www.lsjlt.com/news/170737.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • vue利用openlayers实现动态轨迹
    目录实现效果创建一个地图容器引入地图相关对象创建地图对象创建一条线路画一条线路添加起、终点添加小车准备开车完整代码实现效果 今天介绍一个有趣的gis小功能:动态轨迹播放!效果就像这样...
    99+
    2022-11-13
    vue openlayers动态轨迹 vue openlayers
  • Qt编写地图实现实时动态轨迹效果
    目录一、前言二、功能特点三、体验地址四、效果图五、相关代码一、前言 实时动态轨迹经历过很多个版本的迭代,此功能最初是一个客户定制的,主要是需要在地图上动态显示GPS的运动轨迹,有个应...
    99+
    2024-04-02
  • 如何使用css3实现轨迹运动
    这篇文章主要介绍如何使用css3实现轨迹运动,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!实现效果:实现代码:<div class="haorooms-dot &qu...
    99+
    2024-04-02
  • Unity ScrollRect实现轨迹滑动效果
    本文实例为大家分享了Unity ScrollRect实现轨迹滑动效果的具体代码,供大家参考,具体内容如下 以下内容是根据Unity 2020.1.01f版本进行编写的 1、目的 工作...
    99+
    2024-04-02
  • 如何利用CSS+JS实现唯美星空轨迹运动效果
    小编给大家分享一下如何利用CSS+JS实现唯美星空轨迹运动效果,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!css是什么意思css是一种用来表现HTML或XML等...
    99+
    2023-06-08
  • Unity实现物体运动轨迹的绘制
    本文实例为大家分享了unity物体运动轨迹绘制的具体代码,供大家参考,具体内容如下 ① create empty,命名为LineRender ② 在Assects中新建材质,选择Sh...
    99+
    2024-04-02
  • Unity实现物体运动时画出轨迹
    本文实例为大家分享了Unity实现物体运动时画出轨迹的具体代码,供大家参考,具体内容如下 1、新建空物体,上赋LineRenderer 2、新建空物体,把轨迹画出来,设计和脚本。 ...
    99+
    2024-04-02
  • Vue中的高德轨迹回放怎么实现
    这篇文章主要介绍了Vue中的高德轨迹回放怎么实现的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Vue中的高德轨迹回放怎么实现文章都会有所收获,下面我们一起来看看吧。HTML版高德轨迹回放进入页面后点击开发支持&...
    99+
    2023-07-05
  • VUE引入腾讯地图并实现轨迹动画的详细步骤
    目录效果:引入步骤:效果: 引入步骤: 在 html 中通过引入 script 标签加载API服务在一个盒子元素 div 中预先准备地图容器,并在CSS样式中定义地图(容器)显示大...
    99+
    2024-04-02
  • 如何使用css3实现椭圆轨迹旋转
    这篇文章主要介绍如何使用css3实现椭圆轨迹旋转,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完! css3实现椭圆轨迹旋转最近需要实现如下效果最开始用css...
    99+
    2024-04-02
  • canvas如何实现按住鼠标移动绘制出轨迹
    小编给大家分享一下canvas如何实现按住鼠标移动绘制出轨迹,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!概要工作以来,写过vue、react、正则、算法、小程序...
    99+
    2023-06-09
  • Vue利用openlayers实现点击弹窗的方法详解
    目录解释编写弹窗引入openlayer使用弹窗组件点击事件这个写的稍微简单一点就行了,其实呢,这个不是很难,主要是知道原理就可以了。 我想实现的内容是什么意思呢?就是说页面上有很多坐...
    99+
    2024-04-02
  • 怎么用CSS3和table标签实现一个圆形轨迹的动画
    小编给大家分享一下怎么用CSS3和table标签实现一个圆形轨迹的动画,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!html:其实就是根据table标签把几个实心...
    99+
    2023-06-08
  • 使用css3怎么实现一个椭圆轨迹旋转
    这篇文章将为大家详细讲解有关使用css3怎么实现一个椭圆轨迹旋转,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。X轴Y轴在一个矩形内移动路径为斜线 .ball { ...
    99+
    2023-06-08
  • 微信小程序记录用户移动轨迹的实战记录
    目录添加配置json配置视图层配置逻辑层配置开启定位追踪开始记录确定起始坐标监听位置变化信息按照规则收集定位点信息活动轨迹渲染结束轨迹跟踪总结这篇文章是对微信小程序在关闭的情况下依然...
    99+
    2024-04-02
  • 怎么在Android应用中利用贝塞尔曲线实现一个购物车添加轨迹
    这期内容当中小编将会给大家带来有关怎么在Android应用中利用贝塞尔曲线实现一个购物车添加轨迹,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。效果如下:新建自定义View,重写构造方法,初始化Paint、...
    99+
    2023-05-31
    android 贝塞尔曲线 roi
  • Vue中怎么利用ElementUI实现表单动态渲染
    本篇文章为大家展示了Vue中怎么利用ElementUI实现表单动态渲染,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。{  "inline&quo...
    99+
    2024-04-02
  • 怎么用vue实现动态路由
    这篇文章主要介绍了怎么用vue实现动态路由的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么用vue实现动态路由文章都会有所收获,下面我们一起来看看吧。1、什么是动态路由?动态路由,动态即不是写死的,是可变的。...
    99+
    2023-07-02
  • Vue结合Openlayers使用Overlay添加Popup弹窗实现
    最近使用 Vue 和 Openlayers 写了一个简单的小 dom ,用到了 Overlay 的弹窗功能,记录一下! 实验数据:test.xls 项目运行效果 创建元素: ...
    99+
    2024-04-02
  • vue模态框实现动态锚点
    本文实例为大家分享了vue模态框实现动态锚点的具体代码,供大家参考,具体内容如下 参考:vue中实现锚点跳转及滚动监听的简便方法 效果图: 代码: // html代码 <te...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作