Leaflet -- 绘制台风风圈

  • 实现效果
  • 实现思路
  • 核心代码
  • 全部代码
  • 结束语
实现效果

实现思路

我们先来看一下,后端返回的数据格式。下面是台风轨迹列表中的一条记录,红框的字段就是画台风风圈的关键字段:se、se、ne、nw分别代表当前点位台风风圈的东南、西南、东北、西北四个方向的影响半径。

html的图形的绘制,svg和canvas。最开始选择的是canvas,绘制好了之后,在地图的位移时要重新计算和绘制实现效果不理想。

之后看了下leaflet的源码发现L.Polygon 是继承自L.Path对象。而L.Path本身又是,基于SVG实现的。那就好办了,我们继承L.Polygon再写个类L.Typhoon

L.Typhoon类中,两个最核心方法:一个是计算风圈四个方向半径,一个是绘制台风风圈: 基于SVG的path元素来实现的,下面是代码:

核心代码
  1. 计算风圈半径:台风中心经纬度和半径计算屏幕坐标
projectLatlngs: function () {try {var e = this._latlng;this._point = this._map.latLngToLayerPoint(e);var t_northeast = this._getLngRadius(this._getLatRadius(this._circle.ne * 1000)),i_northeast = this._map.latLngToLayerPoint([e.lat, e.lng - t_northeast]);this._radius_northeast = Math.max(this._point.x - i_northeast.x, 1);var t_southeast = this._getLngRadius(this._getLatRadius(this._circle.se * 1000)),i_southeast = this._map.latLngToLayerPoint([e.lat, e.lng - t_southeast]);this._radius_southeast = Math.max(this._point.x - i_southeast.x, 1);var t_southwest = this._getLngRadius(this._getLatRadius(this._circle.sw * 1000)),i_southwest = this._map.latLngToLayerPoint([e.lat, e.lng - t_southwest]);this._radius_southwest = Math.max(this._point.x - i_southwest.x, 1);var t_northwest = this._getLngRadius(this._getLatRadius(this._circle.nw * 1000)),i_northwest = this._map.latLngToLayerPoint([e.lat, e.lng - t_northwest]);this._radius_northwest = Math.max(this._point.x - i_northwest.x, 1)} catch (e) {this._radius_northeast = null;this._radius_southeast = null;this._radius_southwest = null;this._radius_northwest = null}},
  1. 绘制台风风圈:
getTyphoonPath: function () {if (this._radius_northeast && this._radius_southeast && this._radius_southwest && this._radius_northwest) {var t = this._point;var e_northeast = this._radius_northeast;var path_svg = "M" + t.x + "," + (t.y - e_northeast);var path_vml = "M" + t.x + "," + (t.y - e_northeast);path_svg += "A" + e_northeast + "," + e_northeast + ",0,0,1," + (t.x + e_northeast) + "," + t.y;path_vml += " ae " + t.x + "," + t.y + " " + e_northeast + "," + e_northeast + " " + 65535 * 450 + "," + -5898150;var e_southeast = this._radius_southeast;path_svg += "L" + (t.x + e_southeast) + "," + t.y;path_svg += "A" + e_southeast + "," + e_southeast + ",0,0,1," + t.x + "," + (t.y + e_southeast);path_vml += " ae " + t.x + "," + t.y + " " + e_southeast + "," + e_southeast + " " + 65535 * 360 + "," + -5898150;var e_southwest = this._radius_southwest;path_svg += "L" + t.x + "," + (t.y + e_southwest);path_svg += "A" + e_southwest + "," + e_southwest + ",0,0,1," + (t.x - e_southwest) + "," + t.y;path_vml += " ae " + t.x + "," + t.y + " " + e_southwest + "," + e_southwest + " " + 65535 * 270 + "," + -5898150;var e_northwest = this._radius_northwest;path_svg += "L" + (t.x - e_northwest) + "," + t.y;path_svg += "A" + e_northwest + "," + e_northwest + ",0,0,1," + t.x + "," + (t.y - e_northwest) + "z";path_vml += " ae " + t.x + "," + t.y + " " + e_northwest + "," + e_northwest + " " + 65535 * 180 + "," + -5898150 + "X";this.svgPath = L.Browser.svg ? path_svg : path_vmlreturn L.Browser.svg ? path_svg : path_vml}return ""},
全部代码
(function () {L.Typhoon = L.Polygon.extend({initialize: function (t, e, i) {L.Polygon.prototype.initialize.call(this, e), this._latlng = L.latLng(t), this._circle = e,this._style = i;},options: {fill: !0},projectLatlngs: function () {try {var e = this._latlng;this._point = this._map.latLngToLayerPoint(e);var t_northeast = this._getLngRadius(this._getLatRadius(this._circle.ne * 1000)),i_northeast = this._map.latLngToLayerPoint([e.lat, e.lng - t_northeast]);this._radius_northeast = Math.max(this._point.x - i_northeast.x, 1);var t_southeast = this._getLngRadius(this._getLatRadius(this._circle.se * 1000)),i_southeast = this._map.latLngToLayerPoint([e.lat, e.lng - t_southeast]);this._radius_southeast = Math.max(this._point.x - i_southeast.x, 1);var t_southwest = this._getLngRadius(this._getLatRadius(this._circle.sw * 1000)),i_southwest = this._map.latLngToLayerPoint([e.lat, e.lng - t_southwest]);this._radius_southwest = Math.max(this._point.x - i_southwest.x, 1);var t_northwest = this._getLngRadius(this._getLatRadius(this._circle.nw * 1000)),i_northwest = this._map.latLngToLayerPoint([e.lat, e.lng - t_northwest]);this._radius_northwest = Math.max(this._point.x - i_northwest.x, 1)} catch (e) {this._radius_northeast = null;this._radius_southeast = null;this._radius_southwest = null;this._radius_northwest = null}},getTyphoonPath: function () {if (this._radius_northeast && this._radius_southeast && this._radius_southwest && this._radius_northwest) {var t = this._point;var e_northeast = this._radius_northeast;var path_svg = "M" + t.x + "," + (t.y - e_northeast);var path_vml = "M" + t.x + "," + (t.y - e_northeast);path_svg += "A" + e_northeast + "," + e_northeast + ",0,0,1," + (t.x + e_northeast) + "," + t.y;path_vml += " ae " + t.x + "," + t.y + " " + e_northeast + "," + e_northeast + " " + 65535 * 450 + "," + -5898150;var e_southeast = this._radius_southeast;path_svg += "L" + (t.x + e_southeast) + "," + t.y;path_svg += "A" + e_southeast + "," + e_southeast + ",0,0,1," + t.x + "," + (t.y + e_southeast);path_vml += " ae " + t.x + "," + t.y + " " + e_southeast + "," + e_southeast + " " + 65535 * 360 + "," + -5898150;var e_southwest = this._radius_southwest;path_svg += "L" + t.x + "," + (t.y + e_southwest);path_svg += "A" + e_southwest + "," + e_southwest + ",0,0,1," + (t.x - e_southwest) + "," + t.y;path_vml += " ae " + t.x + "," + t.y + " " + e_southwest + "," + e_southwest + " " + 65535 * 270 + "," + -5898150;var e_northwest = this._radius_northwest;path_svg += "L" + (t.x - e_northwest) + "," + t.y;path_svg += "A" + e_northwest + "," + e_northwest + ",0,0,1," + t.x + "," + (t.y - e_northwest) + "z";path_vml += " ae " + t.x + "," + t.y + " " + e_northwest + "," + e_northwest + " " + 65535 * 180 + "," + -5898150 + "X";this.svgPath = L.Browser.svg ? path_svg : path_vmlreturn L.Browser.svg ? path_svg : path_vml}return ""},beforeAdd: function (map) {this._renderer = map.getRenderer(this);},onAdd: function (map) {this.projectLatlngs();this.getTyphoonPath();this._renderer._initPath(this);this._reset();this._path.setAttribute('d',this.svgPath);this._renderer._addPath(this);this._setStyle(this._style);},_setStyle: function (style) {L.setOptions(this, style);if (this._renderer) {this._renderer._updateStyle(this);}return this;},_getLatRadius: function (r) {return r / 40075017 * 360},_getLngRadius: function (lr) {return lr / Math.cos(Math.PI / 180 * this._latlng.lat)}});L.typhoon = function (t, e, i) {return new L.Typhoon(t, e, i)}})();
结束语

以上就是台风风圈的绘制实现及代码。本文是基于leaflet v1.6.0的完成的,低版本的leaflet是否可以用并未进行测试,请自行进行测试或对代码进行修改。

Leaflet地图 -- 绘制台风风圈相关推荐

  1. 使用mapbox 绘制台风风圈、台风路径

    目录 1.台风路径信息准备与添加 1.1 数据准备,这里可以从中央气象台台风网抓取数据http://typhoon.nmc.cn/web.html 1.2 添加地图信息 2.添加台风风圈 1.使用坐标 ...

  2. 使用leaflet插件绘制手绘地图h5

    手绘地图简介: 手绘地图顾名思义就是手工绘制的地图,比普通的地图更有观赏性和生动性,通过把特定的地点绘制出来,兼具实用和纪念性,同时更加具有可看性. 前期开发准备: 手绘地图绘制. 需要一个专门做手绘 ...

  3. 【MapBox实战】生成地图+绘制区域+纠偏

    [MapBox实战]生成地图+绘制区域+纠偏 mapbox介绍 生成地图过程 基础配置 坐标 在地图上绘制一块区域 在地图上画上点 瓦片地图原理理解 原理 瓦片地图背景理解 编码方式 谷歌xyz 百度 ...

  4. Python 里最强的地图绘制神器

    今天给大家介绍一个非常 NB 的Python 库,专门用来绘制地图的,它叫 Folium . 很多人学习python,不知道从何学起. 很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例 ...

  5. 地图绘制初探——基于maptalks的2.5D地图绘制

    进行图形可视化,难免会遇到地理数据的可视化需求.通常情况下,直接使用echarts对配置项进行处理,就可以满足大部分需求.当然,更加复杂的定制化需求,可能就需要借助d3.Three.js等工具.如果对 ...

  6. leaflet地图总结(不断更新)

    一.创建leaflet地图 输入指令npm install leaflet 页面引入 import L from "leaflet"; import "leaflet/d ...

  7. 关于Leaflet 地图 遮罩反选

    关于Leaflet 地图 遮罩反选 最近项目用到leaflet作为地图开发插件,需要将某个区域突出显示,其余部分隐藏,之前做过百度地图的开发,有过类似的经验,就简单写一下作为记录. leaflet 地 ...

  8. 每日一练:Python国内疫情数据爬取与地图绘制

    Python 国内疫情数据爬取与地图绘制 效果图 累计确诊疫情地图绘制 ① 时时数据抓取 ② 获取省份疫情数据 ③ 视觉配置项分段颜色数据设置 ④ 累计确诊疫情地图绘制 现存确诊疫情地图绘制 ① 获取 ...

  9. 在Leaflet地图上集成Echarts

    需求背景: 现在我要在地图上加上Echarts的散点图还有线集,看起来就很牛B的那种.上效果图: 需求分析: 我先看了看Echarts官网上有提供加载地图的例子,主要包括三种方式: 1.加载js格式的 ...

  10. python台风动图绘制_使用Python绘制台风轨迹图的示例代码

    参考: 使用CMA热带气旋最佳路径数据集,对我国周边的台风进行绘制 import re import os import numpy as np import matplotlib.pyplot as ...

最新文章

  1. TiDB 源码阅读系列文章(十八)tikv-client(上)
  2. oracle数据库函数/存储过程/包区别
  3. Adobe与Facebook联手推出Flash开发工具
  4. 【数据分析R语言系列】R和RStudio的下载和安装, R在 Ubuntu 和CentOS 系统下的安装
  5. 想调试Angular框架的@HostBinding,应该在哪里设置断点
  6. [转][HTML]css属性
  7. 小鹏汽车副总裁纪宇:坚持智能化技术自研,打造最深的护城河
  8. jstl标签库基础教程及其使用代码
  9. refprop用matlab,Matlab 调用 REFPROP(64位)下载即可用
  10. 高等数学(下)知识点总结(1)
  11. java中向上的尖括号是什么_T(尖括号)在Java中是什么意思?
  12. 【PP-15】定义成本构成结构
  13. 上海大学计算机学院领军人物,上海大学计算机工程与科学学院研究生导师简介-谢 江高级工程师...
  14. USB PD快充协议
  15. 补充学习2021.7.21—动态水波进度条
  16. 服务器芯片市场容量,未来内存接口芯片市场规模 使用内存接口芯片的服务器内存模组主要有寄存内存模组(RDIMM)和减载内存模组(LRDIMM)两种。RDIMM需要一颗寄... - 雪球...
  17. 分享课丨微软研究院资深主任研究员郑宇教授:多源数据融合与时空数据挖掘(一)...
  18. 第五期 中断设计 基于ARTY A7的MicroBlaze系统搭建与应用
  19. C# WebAPI 上传文件和图片
  20. Linux之网络性能测试工具netperf实践

热门文章

  1. SaaS商城是什么,赢利点在哪儿?
  2. CTF之Bugku网站被黑
  3. xxl-job集群原理
  4. 物联网的主要特征是什么,目前的主要应用哪些?
  5. 第26讲-项目六-定期存款利息计算器
  6. 【自动化营销】跨境电商高效进行WhatsApp营销技巧!
  7. xgboost 中的二阶导数为什么收敛更快?
  8. 客户消费积分管理系统的设计与实现
  9. 小宝精灵-智能语音遥控伴侣(套装版)测评-遥控器的语音时代
  10. 云计算技术基础【10】