概述

本文在以前风圈生成文章的基础上,将openlayers4+中台风路径的播放展示做了优化,并进行了封装。

说明:
1、本文示例台风数据来自温州台风网;
2、openlayers使用版本为4.6;

效果

实现

封装后的代码为:

var Typhoon = function(map) {{const that = this;that._map = map;that._speed = 200;that._typhoonList = [];that._typhoonData = {};that._nameOverlays = {};that._typhoonPlayFlag = {};that._typhoonPlayIndex = {};that._warnLines = null;that._typhoonLayers = {};that._forecastFeatures = {};that._forcColorDict = {'中国': '#ec5d72','中国香港': '#ec7cfe','中国台湾': '#ecaa65','日本': '#56f66e','美国': '#53dbfe','韩国': '#72a4ac','欧洲': '#4c54a6',};that.init = function() {// 添加警戒线that.addWarnLine();// 添加地图事件that.addMapEvent();// 获取台风数据$.get('../../data/201929.json', res => {that._typhoonList = res;that.showTyphoon(that._typhoonList[0]);})};that.addWarnLine = function() {const warnLineData = [{"color": "blue","weight": 1,"opacity": 0.8,"dashArray": [0, 0],"points": [[105,0,],[113,4.5],[119,11],[119,18],[127,22],[127,34]]},{"color": "green","weight": 1,"opacity": 0.8,"dashArray": [10, 5],"points": [[105,0],[120,0],[132,15],[132,34]]}];const features = [];for (var i = 0; i < warnLineData.length; i++) {const d = warnLineData[i];const geometry = new ol.geom.LineString(d.points);geometry.transform('EPSG:4326', that._map.getView().getProjection());const feature = new ol.Feature({geometry: geometry,attr: d});features.push(feature);}const source = new ol.source.Vector({features: features});that._warnLines = new ol.layer.Vector({source: source,style: that.warnLineStyle,opacity: 0.8});that._map.addLayer(that._warnLines);};// 警戒线样式设置that.warnLineStyle = function(feat) {const attr = feat.get('attr');return new ol.style.Style({stroke: new ol.style.Stroke({color: attr.color,width: attr.weight,lineDash: attr.dashArray})});};// 展示台风that.showTyphoon = function(typhoonData) {const tfbh = typhoonData.tfbh;that._typhoonData[tfbh] = typhoonData;// 1. 添加台风名称that.addNameOverlay(typhoonData);// 2. 创建展示图层that.addTyphoonLayer(tfbh);// 3.开始播放that.playTyphoon(tfbh);};// 移除台风that.removeTyphoon = function(tfbh) {// 删除台风名称that._map.removeOverlay(that._nameOverlays[tfbh]);// 删除展示图层that._map.removeLayer(that._typhoonLayers[tfbh].layer);// 消除定时器clearInterval(that._typhoonPlayFlag[tfbh]);};// 添加台风名称that.addNameOverlay = function(typhoonData) {const nameDom = document.createElement('div');nameDom.setAttribute('class', 'typhoon-name');nameDom.innerHTML = typhoonData.name;const pointStart = typhoonData.points[0];const position = ol.proj.fromLonLat([pointStart.longitude, pointStart.latitude]);const nameOverlay = new ol.Overlay({element: nameDom,position: position,positioning: 'center-left',offset: [15, 0]});that._map.addOverlay(nameOverlay);that._nameOverlays[typhoonData.tfbh] = nameOverlay;};// 根据编号添加台风图层that.addTyphoonLayer = function(tfbh) {const source = new ol.source.Vector({features: []});const layer = new ol.layer.Vector({source: source,style: that.typhoonStyle});that._map.addLayer(layer);that._typhoonLayers[tfbh] = {source: source,layer: layer}that._forecastFeatures[tfbh] = [];};// 添加地图事件that.addMapEvent = function() {// 鼠标移动事件that._map.on('pointermove', function(evt) {const pixel = evt.pixel;const dom = that._map.getTargetElement();if(that._map.hasFeatureAtPixel(pixel)) {dom.style.cursor = 'pointer';const features = that._map.getFeaturesAtPixel(pixel);const feature = features[0];// console.log(feature.get('attr'));} else {dom.style.cursor = 'default';}});that._map.on('click', function(evt) {const pixel = evt.pixel;if(that._map.hasFeatureAtPixel(pixel)) {const features = that._map.getFeaturesAtPixel(pixel);const feature = features[0];const attr = feature.get('attr');that._typhoonPlayIndex[attr.tfbh] = attr.index;that.showForecast(attr.tfbh, attr);}});};// 播放台风that.playTyphoon = function(tfbh) {let index = 0;const typhoonData = that._typhoonData[tfbh];that.play(index, tfbh);that._typhoonPlayFlag[tfbh] = setInterval(function() {index++;if (index === typhoonData.points.length) {clearInterval(that._typhoonPlayFlag[tfbh]);} else {that.play(index, tfbh);}}, that._speed);};// 播放单个点that.play = function(index, tfbh) {// 删除预报that.removeForecast(tfbh);that._typhoonPlayIndex[tfbh] = index;const points = that._typhoonData[tfbh].points;const point = points[index];point.type = 'live';point.index = index;point.tfbh = tfbh;if (index > 0) {const prePoint = points[index - 1];point.start = [prePoint.longitude, prePoint.latitude];}point.end = [point.longitude, point.latitude];const coords = ol.proj.fromLonLat(point.end);const feature = new ol.Feature({geometry: new ol.geom.Point(coords),attr: point});that._typhoonLayers[tfbh].source.addFeature(feature);// 最后一个实况点,展示预报路径if (index === that._typhoonData[tfbh].points.length - 1) {that.showForecast(tfbh, point);}};// 删除预报数据that.removeForecast = function(tfbh) {const source = that._typhoonLayers[tfbh].source;for (var i = 0; i < that._forecastFeatures[tfbh].length; i++) {const f = that._forecastFeatures[tfbh][i];source.removeFeature(f);}that._forecastFeatures[tfbh] = [];}// 展示预报数据that.showForecast = function(tfbh, livePoint) {const source = that._typhoonLayers[tfbh].source;// 1. 删除预报数据that.removeForecast(tfbh);// 2. 添加预报const forecast = livePoint.forecast;const features = [];for (var i = 0; i < forecast.length; i++) {const f = forecast[i];for (var j = 0; j < f.points.length; j++) {const point = f.points[j];const prePoint = f.points[j - 1];point.sets = f.sets;point.type = 'forc';point.index = j;point.start =j === 0 ?[livePoint.longitude, livePoint.latitude] :[prePoint.longitude, prePoint.latitude];point.end = [point.longitude, point.latitude];const coords = ol.proj.fromLonLat(point.end);const feature = new ol.Feature({geometry: new ol.geom.Point(coords),attr: point});features.push(feature);}}source.addFeatures(features);that._forecastFeatures[tfbh] = features;}// 台风展示样式that.typhoonStyle = function(feat) {const attr = feat.get('attr');const speed = attr.speed;const type = attr.type;const index = attr.index;const color = that.getPointColor(speed);let styles = [];// 点的样式const radius = type === 'live' ? 4 : 3;const pointStyle = new ol.style.Style({image: new ol.style.Circle({radius: radius,fill: new ol.style.Fill({color: color}),stroke: new ol.style.Stroke({color: 'rgba(0, 0, 0, 0.6)',width: 1})})});styles.push(pointStyle);if (type === 'live' && index === that._typhoonPlayIndex[attr.tfbh]) {const center = feat.get('geometry').getCoordinates();const fillStyle = new ol.style.Fill({color: 'rgba(0, 0, 0, 0.2)'});// 7级风圈的样式if(attr.radius7 > 0) {const geometry = that.getCircleGeometry(center, attr.radius7_quad);const style = new ol.style.Style({geometry: geometry,stroke: new ol.style.Stroke({color: '#00bab2',width: 1}),fill: fillStyle});styles.push(style);}// 10级风圈的样式if(attr.radius10 > 0) {const geometry = that.getCircleGeometry(center, attr.radius10_quad);const style = new ol.style.Style({geometry: geometry,stroke: new ol.style.Stroke({color: '#ffff00',width: 1}),fill: fillStyle});styles.push(style);}// 12级风圈的样式if(attr.radius12 > 0) {const geometry = that.getCircleGeometry(center, attr.radius12_quad);const style = new ol.style.Style({geometry: geometry,stroke: new ol.style.Stroke({color: '#da7341',width: 1}),fill: fillStyle});styles.push(style);}}// 线的样式const start = attr.start;const end = attr.end;const lineColor = that.getLineColor(type, attr.sets);const lineDash = type === 'live' ? [0] : [8];const lineWidth = type === 'live' ? 2 : 1;if(start && start.length > 0) {const coords = [start, end];const geometry = new ol.geom.LineString(coords);geometry.transform('EPSG:4326', that._map.getView().getProjection());const lineStyle = new ol.style.Style({geometry: geometry,stroke: new ol.style.Stroke({color: lineColor,width: lineWidth,lineDash: lineDash})});styles.push(lineStyle);}return styles;};// 获取线的颜色that.getLineColor = function(type, sets) {if (type === 'live') {return 'rgba(0, 0, 0, .6)';} else {let color = that._forcColorDict[sets];if (!color) color = 'rgba(0, 0, 0, .3)';return color;}};// 根据风速获取点的颜色that.getPointColor = function(_speed) {let _color = '';if (_speed >= 10.8 && _speed < 17.2) {_color = 'rgba(153, 255, 153, .9)';} else if (_speed >= 17.2 && _speed < 24.5) {_color = 'rgba(102, 204, 255, .9)';} else if (_speed >= 24.5 && _speed < 32.7) {_color = 'rgba(255, 255, 102, .9)';} else if (_speed >= 32.7 && _speed < 41.5) {_color = 'rgba(253, 139, 0, .9)';} else if (_speed >= 41.5 && _speed < 50.1) {_color = 'rgba(255, 51, 0, .9)';} else {_color = 'rgba(255, 0, 255, .9)';}return _color;};that.getCircleGeometry = function(center, radiusData) {if (typeof radiusData === 'number') {return new ol.geom.Circle(center, radiusData * 1000);} else {if (radiusData['ne']) {let _coords = [];let _angInterval = 6;let _pointNums = 360 / (_angInterval * 4);let quadrant = {// 逆时针算角度'0': 'ne','1': 'nw','2': 'sw','3': 'se'};for (let i = 0; i < 4; i++) {let _r = parseFloat(radiusData[quadrant[i]]) * 1000; // 单位是kmif (!_r) _r = 0;for (let j = i * _pointNums; j <= (i + 1) * _pointNums; j++) {let _ang = _angInterval * j;let x = center[0] + _r * Math.cos((_ang * Math.PI) / 180);let y = center[1] + _r * Math.sin((_ang * Math.PI) / 180);_coords.push([x, y]);}}return new ol.geom.Polygon([_coords]);} else {return null;}}}}
}

说明
1、本文中做了优化最多的部分是typhoonStyle,将实况线、预报线、台风风圈等内容均通过style的方式实现;
2、在计算实况线、预报线的时候直接进行了数据层面的处理,方便后续再用。

调用

调用非常简单,传入一个map对象,并调用init()方法即可。

const typhoon = new Typhoon(map);
typhoon.init();

技术博客
CSDN:http://blog.csdn.NET/gisshixisheng
联系方式

类型 内容
qq 1004740957
公众号 lzugis15
e-mail niujp08@qq.com
webgis群 452117357

openlayers4+中台风路径播放优化相关推荐

  1. ArcGIS在线应用介绍(2)中央气象台台风路径系统

    http://www.giser.net/?p=315 中央气象台台风路径系统 开发语言:flex SDK:ArcGIS API for Flex ArcGIS产品:ArcGIS Server 在线地 ...

  2. 【附可运行代码】剑指 Offer 12. 矩阵中的路径

    立志用最少的代码做最高效的表达 给定一个 m x n 二维字符网格 board 和一个字符串单词 word .如果 word 存在于网格中,返回 true :否则,返回 false . 单词必须按照字 ...

  3. 语音识别维特比解码_HMM连续语音识别中Viterbi算法的优化及应用

    HMM 连续语音识别中 Viterbi 算法的优化及应用 袁俊 [期刊名称] <电子技术> [年 ( 卷 ), 期] 2001(028)002 [摘要] 基于 HMM 连续语音识别系统声学 ...

  4. 网站SEO优化中内部链接的优化

    重要性:内链有效的优化能够间接的提高某页面的权重达到搜索排名靠前的效果.同时有效的带领搜索引擎蜘蛛对整站进行抓取. 网站头部导航: 这个导航称为'网站主导航',当用户来到网站需要给他们看到的内容.也就 ...

  5. 学习中碰到的一些优化工具包和库

    1.linear svm 这个工具包目前用的比较多.例如面部特征点的回归方法中,学习线性回归的权重,例如:Face Alignment at 3000 FPS中: minWt∑i=1N||△s^ti− ...

  6. 地图导航中的路径规划算法(综述)

    综述介绍+本人研究与实践结果--实际是论文 相关的路径规划算法,静态路网中,通常使用双向A*算法 常见的其他搜索算法,IA*(迭代A*),内存限定A*,分层路网A*(将高速路网构建成一个新的路网), ...

  7. 低延迟音频中的音频解码优化策略

    文章目录 前言 音频播放 举个例子:PortAudio 回调函数 解码与播放 优化策略 1. 一次性读取音频到内存中 2. MMAP 3. 音频转码,再接 MMAP 4. 解码缓冲 总结 参考资料 前 ...

  8. python台风动图绘制_python可视化绘图:台风路径可视化

    本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理 以下文章来源于好奇心Log ,作者洋流 台风是重大灾害性天气,台风引起的直接灾害通 ...

  9. android 音频播放过程,一种Android系统中的音频播放方法与流程

    本申请涉及android系统技术,特别涉及一种android系统中的音频播放方法. 背景技术: 在android系统中,现有的使用audiotrack进行音频播放时,audiotrack应用与andr ...

最新文章

  1. Redisson 是如何实现分布式锁的?
  2. 基于xmpp openfire smack开发之smack类库介绍和使用[2]
  3. mjpg-streamer在Ubuntu下编译,运行
  4. 论文笔记:PointNet
  5. JS模式--职责链模式
  6. 做组织机构树状图 spark
  7. 卡尔曼滤波与组合导航原理_卫星知识科普:一种基于卫星共视的卡尔曼滤波算法!...
  8. Qt——鼠标拖动调整窗口大小
  9. 马里奥AI实现方式探索 ——神经网络+增强学习
  10. 中国智慧VS西方智慧-看中国IT风云与IT产业怪状
  11. 机器学习中各科目基本概念集合
  12. Navicat for PostgreSQL 怎么维护数据库和表
  13. [最短路-Floyd][数学]Luogu P1552 牛的旅行
  14. 写出python的基本语法规则_【Python基础】python基本语法规则有哪些-赵小刀的回答...
  15. phpeclipse
  16. 【算法】基于AOE网的关键路径算法
  17. 采集天眼查的10个经典方法
  18. java 三维数组 魔方_三维数组的横向/纵向输出
  19. 获取所有选中的复选框
  20. 你是开发工程师、程序员还是码农?

热门文章

  1. [ZT]crontab 调度程序按时执行
  2. 自动驾驶仿真软件SCANeR studio(初级练习1):scenario构建之driver模式理解
  3. python 根据身份证号计算年龄和性别_excel如何根据身份证号计算男女出生日期、性别和年龄?分享了!...
  4. Daz导出模型的部件中英文对照
  5. Java学习-发红包案例
  6. 大数据架构Spark 进阶
  7. 电话销售话术模板有哪些 电话销售技巧
  8. 微信小程序+SpringBoot实现校园快递代收平台
  9. Oracle 12c 数据库的环境搭建以及安装过程
  10. 树莓派 Raspberry 4B 刷机、上网、录音外设、文件传输、电脑投屏问题汇总