echarts symbol 回调函数_【OpenLayer 实战】实现仿Echarts风格的动态迁徙图/航班图

a7749cf58cee907397dcba96c598c2f5.png

使用的数据还是来自echarts,模拟了全国各地到湖南重点景区的客流情况。

32703f19143b57fa3d75dd849bfb1fe6.gif

分析
要实现动态迁徙图的效果,主要需解决两个问题
    曲线的绘制。因为给出的数据只有起点和终点两个点位,所以想要绘制曲线可以参考turf中的bezier曲线生成API。
    点迹的动画播放。仍然要依靠render机制,这里我还是使用比较熟悉的postrender事件回调函数。
实现
首先利用turf做一个利用两个点就可以生成弧线要素的函数,其实这里面调用的是turf的bezierSpline,写死了一个定比例取到的点位,参数列表为要素的自定义属性留了位置。同时在函数里计算出曲线的长度待用。 

function getTurfArcFeature(start, end, opt) {  var line = turf.lineString([    start,    [start[0] + (end[0] - start[0]) * 0.5,    start[1] + (end[1] - start[1]) * 0.65],    end  ]);  var curved = turf.bezierSpline(line);  let length = turf.length(curved, { units: 'meters' });  var bF = turfFormat.readFeature(curved);  bF.getGeometry().transform('EPSG:4326', 'EPSG:3857');  bF.setProperties(opt);  bF.set("length", length);  return bF;}

然后重点分析一下点位动画的实现:

先写出监听postrender事件回调函数的基本框架,并取得VectorContex对象的句柄:

tileLayer.on('postrender', (evt) => {  let veContext = getVectorContext(evt);  })

再写出遍历所有曲线的forEach结构及回调函数,回调函数内先将本次迭代的曲线绘制到地图上:

tileLayer.on('postrender', (evt) => {  let veContext = getVectorContext(evt);   arcLinesFeature.forEach((item,index) => {    veContext.drawFeature(item, arcStyle);   })  })

然后通过frameState获取当前帧的时间戳,计算得到当前帧运动点位的位置百分比,如果百分比超过100%还要进行归零处理

tileLayer.on('postrender', (evt) => {  let veContext = getVectorContext(evt);  arcLinesFeature.forEach((item,index) => {    veContext.drawFeature(item, arcStyle);        let time = (evt.frameState.time - item.get('start')) / 1000;    let frac = time / 5-index/arcLinesFeature.length;    if (!item.get('start')) item.set('start', new Date().getTime());    if (frac>=1) {      item.set('start', new Date().getTime());      frac=0;    }      }) })

最后根据位置百分比,使用getCoordinateAt求得点位的坐标,并且使用VectorContex对象绘制到canvas上,然后显示调用render()函数,请求渲染下一帧。

tileLayer.on('postrender', (evt) => {  let veContext = getVectorContext(evt);  arcLinesFeature.forEach((item,index) => {    veContext.drawFeature(item, arcStyle);    let time = (evt.frameState.time - item.get('start')) / 1000;    let frac = time / 5-index/arcLinesFeature.length;    if (!item.get('start')) item.set('start', new Date().getTime());    if (frac>=1) {      item.set('start', new Date().getTime());      frac=0;    }    let along = item.getGeometry().getCoordinateAt(frac);    let pF=new Feature(new Point(along));    veContext.drawFeature(pF, dotStyle);  })  map.render()})

完整代码

(删掉了我自己的Google开发者Key,黑色主题地图还请自己动手做一个)

import { Map, View } from 'ol';import TileLayer from 'ol/layer/Tile';import XYZ from 'ol/source/XYZ';import Point from 'ol/geom/Point';import VectorSource from 'ol/source/Vector';import VectorLayer from 'ol/layer/Vector';import Feature from 'ol/Feature';import * as turf from '@turf/turf'import GeoJSON from 'ol/format/GeoJSON'import { getVectorContext } from 'ol/render';import Style from 'ol/style/Style';import Stroke from 'ol/style/Stroke';import Fill from 'ol/style/Fill';import CircleStyle from 'ol/style/Circle';import data from './data/t.json' let tileLayer = new TileLayer({  source: new XYZ({    url: 'http://www.google.cn/maps/vt?pb=!1m5!1m4!1i{z}!2i{x}!3i{y}!4i256!2m3!1e0!2sm!3i451159038!3m14!2szh-CN!3sUS!5e18!12m1!1e68!12m3!1e37!2m1!1ssmartmaps!12m4!1e26!2m2!1sstyles!2zcC5oOiNmZjFhMDB8cC5pbDp0cnVlfHAuczotMTAwfHAubDozM3xwLmc6MC41LHMudDo2fHMuZTpnfHAuYzojZmYyRDMzM0M!4e0&key=&token=126219'  })})let map = new Map({  target: 'map',  layers: [    tileLayer  ],  view: new View({    center: [11936406.337013, 3786384.633134],    zoom: 5  })}); var flightSource = new VectorSource()var flightLayer = new VectorLayer(  {    source: flightSource  })var turfFormat = new GeoJSON(); function getTurfArcFeature(start, end, opt) {  var line = turf.lineString([    start,    [start[0] + (end[0] - start[0]) * 0.5,    start[1] + (end[1] - start[1]) * 0.65],    end  ]);  var curved = turf.bezierSpline(line);  let length = turf.length(curved, { units: 'meters' });  var bF = turfFormat.readFeature(curved);  bF.getGeometry().transform('EPSG:4326', 'EPSG:3857');  bF.setProperties(opt);  bF.set("length", length);  return bF;} map.addLayer(flightLayer) var arcStyle = new Style({  stroke: new Stroke({    color: [0, 122, 122, 0.7],    width: 1  })}) var dotStyle = new Style({  image: new CircleStyle({    fill: new Fill({      color: [255, 255, 255,0.7]    }),    radius: 1   })}) var arcLinesFeature = [];data.moveLines.forEach((item, index) => {  let tempF = getTurfArcFeature(item.coords[0], item.coords[1], { 'from': item.fromName, 'to': item.toName });  arcLinesFeature.push(tempF);}) tileLayer.on('postrender', (evt) => {  let veContext = getVectorContext(evt);  arcLinesFeature.forEach((item,index) => {    veContext.drawFeature(item, arcStyle);    let time = (evt.frameState.time - item.get('start')) / 1000;    let frac = time / 5-index/arcLinesFeature.length;    if (!item.get('start')) item.set('start', new Date().getTime());    if (frac>=1) {      item.set('start', new Date().getTime());      frac=0;    }    let along = item.getGeometry().getCoordinateAt(frac);    let pF=new Feature(new Point(along));    veContext.drawFeature(pF, dotStyle);  })  map.render()}) 

【OpenLayers】OpenLayers概述

【OpenLayers】实现简单的地图显示

【OpenLayers】地图控件之缩放控件

【OpenLayers】归属控件与全屏控件

【OpenLayers】地图控件之坐标拾取控件和鹰眼控件

【OpenLayers】地图控件之旋转控件与比例尺控件

【OpenLayers】实现图层切换控件

【OpenLayers】多源数据加载之数据组织

【OpenLayers】多源数据加载之瓦片地图原理一

【OpenLayers】多源数据加载之瓦片地图原理二

【OpenLayers】多源数据加载之用最简单的方式加载瓦片地图

【OpenLayers】多源数据加载之使用XYZ的方式加载瓦片地图

【OpenLayers】多源数据加载之详解OpenLayers的瓦片坐标系

【OpenLayers】多源数据加载之离线瓦片地图

【OpenLayers】多源数据加载之矢量地图

【OpenLayers】多源数据加载之WMS(一)

【OpenLayers】多源数据加载之WMS(二)

【OpenLayers】多源数据加载之矢量切片

【OpenLayers】多源数据加载之WMTS

【OpenLayers】图形绘制之设置图形的样式

【OpenLayers】图形绘制之编辑图形

【OpenLayers】使用GeoJSON数据渲染热力图

【OpenLayers】实现“上一视图”、“下一视图”的视图切换功能

【OpenLayers】图文标注

【OpenLayers】聚合标注

【OpenLayers】图层卷帘(Layer Swipe)

【OpenLayers】Drag-and-Drop Image Vector

【OpenLayer 实战】实现克里金插值渲染图-Kriging

【OpenLayer 实战】请求Geoserver带Filter的WFS查询

【OpenLayer 实战】使用GeoJSON进行行政区划剪裁(clip, not mask or filter)

END

 

请:右下点在看a682a6ff971c2980c48e80620801afb6.gif,右上点【···】分享

2f01b72d1e3c448c6dacf074895594b1.png

关注我

发现更多精彩

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

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

相关文章

校运会计算机科学系大本营,计算机系团总支学生会学期总结大会

(本网讯)时光飞逝,又一个学期即将就此画上了圆满的句号。为推动我系团总支学生会工作更长久的发展,提高学生会干部工作的热情和质量,2016年12月8日晚上19:00在第一教学楼C102课室里,校学生会全体成员齐聚一堂,参加了20…

hexo评论_【前端简历加分】hexo框架搭建个人博客站点,手把手教学

最近,粉丝们在金九银十期间也是不断的面试,有比较多的毕业生说我在这个期间出多一些面试题,上几期都是倾向于面试文章,这期出一次简历加分项操作,使用hexo框架搭建个人博客。作为应届毕业生或者1-3年工作经验的程序员拥…

电脑抓整个路由器的包_网络是电竞游戏体验的命脉 2018年年度电竞路由器功能盘点...

2018年是电竞路由器的元年,从2017年的概念产品诞生开始,电竞路由器很快就确定了品类,随着《绝地求生》、《王者荣耀》等对网络质量敏感的竞技游戏的火爆,电竞路由器迅速被竞技玩家熟知,并在2018年以野火燎原的速度发展…

dos 改某个目录下所有文件的时间_go语言入门学习笔记(2)-DOS操作及go语言变量学习...

API:application program interface:应用程序编程接口。就是我们go的各个包的各个函数。我们想要了解这些函数我们可以通过Go的中文网在线标准库文档:https://studygolang.com/pkgdocDOS介绍:Dos:Disk Operating System 磁盘操作系…

es multi match_PHP 的ES搜索操作

原文:https://blog.csdn.net/JineD/article/details/106650695首先从ES的支持的字段说起,ES文档中字段有多种类型 官方文档。这几个比较常用:text,keyword,integer,float,boolean,object,geo_point(地理坐标),geo_shape(描述地理区域),date.注…

git 怎么还原历史版本_4. Git--修改/回退等操作

》》点赞,收藏关注,理财&技术不迷路《《我们已经成功地添加并提交了一个readme.txt文件,现在,是时候继续工作了,于是,我们继续修改readme.txt文件,改成如下内容:Git is a distri…

为什么用python写爬虫_零基础,是怎么开始写Python爬虫的

刚开始接触爬虫的时候,简直惊为天人,十几行代码,就可以将无数网页的信息全部获取下来,自动选取网页元素,自动整理成结构化的文件。利用这些数据,可以做很多领域的分析、市场调研,获得很多有价值…

datatable怎么根据两列分组_谈谈怎么做服务隔离

来源于公众号孤独烟 ,作者孤独烟引言OK,如下图所示那显而易见,做服务隔离的目的就是避免服务之间相互影响。毕竟谁也不能说自己的微服务百分百可用,如果不做隔离,一旦一个服务出现了问题,整个系统的稳定性都…

position: absolute;_前端性能优化--transform与position

上个星期去yy语音面试&#xff0c;就有一个这样问题&#xff1a; transform与position:absolute 有什么区别? 我回家后查资料发现这道题目其实不简单啊&#xff0c;涉及到重排、重绘、硬件加速等网页优化的知识。首先看一个用top、left实现的动画效果<style>html,body {…

台式计算机总是重启,台式电脑经常自动重启怎么修复

当我们的电脑出现了电脑自动重启的时候&#xff0c;我们就要注意了&#xff0c;说明我们的电脑主机出现问题了&#xff0c;怎么解决呢。下面是学习啦小编为大家整理的关于台式电脑经常自动重启的相关资料&#xff0c;希望对您有所帮助!台式电脑经常自动重启的解决方法方法/步骤…

线程执行完之后会释放吗_java多线程并发:CAS+AQS+HashMap+volatile+ThreadLocal,乐分享...

CyclicBarrier、CountDownLatch、Semaphore 的用法CountDownLatch(线程计数器 )CountDownLatch 类位于 java.util.concurrent 包下&#xff0c;利用它可以实现类似计数器的功能。比如有一个任务 A&#xff0c;它要等待其他 4 个任务执行完毕之后才能执行&#xff0c;此时就可以…

计算机应用基础考查方案,《计算机应用基础》考查方案

《计算机应用基础》考查方案 《计算机应用基础》考核方案 制订人&#xff1a;刘久红老师 计算机应用基础科任教师 制订部门&#xff1a;基础课与思政课教学部 制订时间&#xff1a;2012年12月 一&#xff1a;考核依据 计算机应用基础是面向全院各专业开设的一门重要的公共基础课…

无法启动此程序因为计算机丢失msvcr110.dll,计算机中丢失msvcr110.dll怎么办

我们在打开电脑程序的时候&#xff0c;系统提示无法启动此程序&#xff0c;因为计算机中丢失MSVCR110.dll&#xff0c;尝试重新安装该程序以解决此问题。这是什么情况呢?因为现在所有的5.5环境都是基于vc11的编译脚本下生成的&#xff0c;所以在windows下你得安装相关组件&…

anaconda pandas运行不了_学习python你必须弄懂的 Python、Pycharm、Anaconda 三者之间的关系...

Python作为深度学习和人工智能学习的热门语言&#xff0c;学习一门语言&#xff0c;除了学会其简单的语法之外还需要对其进行运行和实现&#xff0c;才能实现和发挥其功能和作用。下面来介绍运行Python代码常用到的工具总结。一.Python、Pycharm、Anaconda关系介绍1. PythonPyt…

java: 程序包com.alibaba.fastjson不存在_Java开发中的异常

NO.1 Java.alng.NullPointerException这个异常大家肯定都经常遇到&#xff0c;异常的解释是 “程序遇上了空指针 “&#xff0c;简单地说就是调用了未经初始化的对象或者是不存在的对象&#xff0c;这个错误经常出现在创建图片&#xff0c;调用数组这些操作中&#xff0c;比如图…

关于csgo的观看录像fps低_CSGO:Ququ带队击败LQ豪取五连冠,8次MVP闪耀全场

电子竞技热点资讯&#xff0c;敬请关注老年人三旬&#xff01;自从CSGO这款游戏上市之后&#xff0c;在整个FPS领域内就一直处于顶流位置&#xff0c;这款游戏对于所有热爱射击游戏的玩家来说&#xff0c;不但是经典作品《半条命》的延续&#xff0c;更是一款对玩家要求极高的游…

python 3d大数据可视化_基于Python的数据可视化库pyecharts介绍

什么是pyecharts&#xff1f; pyecharts 是一个用于生成 Echarts 图表的类库。 echarts 是百度开源的一个数据可视化 JS 库&#xff0c;主要用于数据可视化。pyecharts 是一个用于生成 Echarts 图表的类库。实际上就是 Echarts 与 Python 的对接。 使用 pyecharts 可以生成独立…

dev多行注释_Python代码注释的用法和意义

01. 注释的作用在大多数编程语言中&#xff0c;注释都是一项很有用的功能。在一些简单的程序中只包含Python代码&#xff0c;但随着程序越来越大、越来越复杂&#xff0c;就应在其中添加说明&#xff0c;对你解决问题的方法进行大致的阐述。注释让你能够使用熟悉的自然语言在程…

python的数据库_python数据库操作-mysql数据库

一&#xff1a;连接 1&#xff1a;本地连接 mysql -u用户名 -p密码 2&#xff1a;连接远程服务器 mysql -u用户名 -p密码 -hip地址 -P端口号 线下修改远程服务端上部署的mysql服务器 二&#xff1a;创建数据库 create database 名字 utf8; 三&#xff1a;显示数据库 show datab…

svn如何取消某个文件的版本管理_微服务架构如何统一管理工程配置文件

面临的问题在分布式微服务架构系统中&#xff0c;业务和系统功能被拆分成了几十甚至上百个服务实例。每个服务实例就是以往单体应用时代的一个独立部署的工程。每个工程都需要自己独立的启动加载和运行时配置文件。在项目开发的过程中&#xff0c;我们不可避免的会涉及到配置文…