点击上方 前端瓶子君,关注公众号

回复算法,加入前端编程面试算法每日一题群

记录了我在组内的技术分享, 有同样需求的同学可以参考一下
分享全程下来时间大约 70分钟

image

一. 为什么要分享前端相关的"地图"知识

  1. (大屏展示)很多公司都会有相应的大屏幕展示系统, 例如中国或者全世界的客户与资产分布图.

  2. (生动描绘)用地图的角度来展示地理方面的关系, 让人看着比单纯的文字更直观

  3. (场景多)比如今年的各类疫情严重情况的分布图.

  4. 总的来说还是看起来比较炫酷, 可以提升一点点b格, 并且这个只是也是属于前端的范畴, 那么我们就有必要弄懂它.

二. 做地图相关技术简介

这里我只介绍几款我常用的

** 百度地图
这个名气太大了, 功能很多并且现在对3d的支持也很不错, 注意GL版v1.0 与之前 v2.0版本地图的api有点不一样别掉坑里.
缺点也比较明显, 比如你想要一份干干净净的地图, 上面没有店铺没有任何标识的时候我就建议你用echarts来玩了, 因为百度地图带的东西比较多.
想要使用百度地图的同学可以看这里, 超级简单就可以完成注册用玩耍.
使用非常简单

** hcharts
非常牛非常好用, 但是它部分功能是要收费的, 使用之前要让公司帮你买好相应的功能才能用于商用哦.
由于我们公司地图库是自己研发的最后也就没有这种网上付费的.
详情地址

** echarts
这个库前端无人不知了, 在需求很简单的情况下建议用这个技术来做, 大部分时候项目中需要绘制柱状图或折线图的时候已经引入了echarts此时不用重复引用来节省空间.
echarts画的地图

** 我们公司自己的2d, 3d地图组件库
这个在这里就不做过多详细介绍了, 一些公司也会有自主研发的地图组件, 设计的思想上可能与上面三个不太相同, 接下来我也会聊到.

三.echarts实现基础地图

以echarts为例是因为这个最好弄...

这里我新建了一个vue工程

<template><div class="home"><div id="map"></div></div>
</template><script>
import echarts from "echarts";
import mapData from "./geo";export default {name: "Home",data() {return {myChart: null,};},methods: {initMap() {this.myChart = echarts.init(document.getElementById("map"));echarts.registerMap("world", mapData); // 定义名称下面要用, 这样做的好处就是可以很方便的实现切换地图的效果this.myChart.setOption({series: [{type: "map",mapType: "world", // 自定义扩展图表类型label: {show: false,},},],});},},mounted() {this.initMap();}
};
</script>
  1. 像我们平时使用echarts一样先初始化

  2. 接下来有点不同需要echarts.registerMap("world", mapData); 可以理解为把这个数据命名为'world', 方便以后的切换(这里的数据我下面会讲).

  3. 在option的配置里面设置类型是地图, 使用上面定义好的'world'类型.

效果图

我们可以看得出来, 地图的绘制也没什么'特殊'的, 最主要的就是那个 mapData数据, 这个数据一般叫它geojson数据, 那么接下来我们认识一下它.

四.geojson数据到底是什么

  1. geojson是用json的语法表达和存储地理数据,可以说是json的子集, 它不是专门js使用的这点要清楚.

  2. 地图上有山川, 河流, 海洋等等的地理信息, 那么如何描述一条河? 这个时候就要使用geojson格式的文件来描绘.

  3. 并不是必须用geojson, geojson只是一套规范, 各大解析器用这套规范来解析生成对应的景色, 我们完全可以制定自己的规范来实现这些, 无非是兼容性不好需要自己写绘制的解析器.

五.geojson详细介绍

英语好的可以先撸网站
1. 基本结构

{ // 可以包括点线面, 一个大的集合"type": "FeatureCollection", // 定义这个是个geojson文件, 这里还可以是其他值下面会说"features": [] // 这里放要绘制的数据
}

以后我们看到"type": "FeatureCollection"这样一行就说明这个文件是geojson规范的文件

2. 描述一个点(Feature)
地图上的打点数据

{"type": "FeatureCollection","features": [{"type": "Feature",  // 表示这个对象是一个要素"properties": {}, // 这里放样式, 后面会专门说"geometry": { // 这里面放具体的数据"type": "Point",  // 专指画点"coordinates": [105.380859375, 31.57853542647338] // 默认是经度与纬度, 三维的话就是xyz三个值, 当然这里也不一定是经纬度(不同的坐标体系)中会讲为什么}},]
}

3. 描述多个点(FeatureCollection)
**优点

  1. 写法简洁

  2. 这些点样式可以共用

{"type": "FeatureCollection","features": [{"type": "Feature","properties": {},"geometry": {"type": "MultiPoint", // 多点, 也就是连续画多个同样的点"coordinates": [[105.380859375, 31.57853542647338],[105.580859375, 31.52853542647338]]}},]
}

4. 描述一条线(LineString)

  1. 这里还是描绘每一个点, 但这些点会连接在一起形成线

  2. 地图上的连线数据

{"type": "FeatureCollection","features": [{"type": "Feature","properties": {},"geometry": {"type": "LineString", // 这里所有的点会连接在一起形成线"coordinates": [[105.6005859375, 30.65681556429287],[107.95166015624999, 31.98944183792288],[109.3798828125, 30.031055426540206],[107.7978515625, 29.935895213372444]]}},]
}

5. 描述多条线(MultiLineString)

  1. 这里第二组与第一组的线, 可以分隔开不会首尾相连.

{"type": "FeatureCollection","features": [{"type": "Feature","properties": {},"geometry": {"type": "MultiLineString","coordinates":[[[105.6005859375, 30.65681556429287],[107.95166015624999, 31.98944183792288],[109.3798828125, 30.031055426540206],[107.7978515625, 29.935895213372444]],[[109.3798828125, 30.031055426540206],[107.1978515625, 31.235895213372444]]]}},]
}

6. 描述一个面(Polygon, 也叫多边形)

  1. 第一个点与最后一个点要相同, 这样才能完成闭环!!

  2. 三维数组的格式需要注意

{"type": "FeatureCollection","features": [{"type": "Feature","properties": {},"geometry": {"type": "Polygon", // 注意这里是三维数组"coordinates": [[[106.10595703125, 33.33970700424026],[106.32568359375, 32.41706632846282],[108.03955078125, 32.2313896627376],[108.25927734375, 33.15594830078649],[106.10595703125, 33.33970700424026]]]}},]
}

7. 一个面里面有多个面(Polygon)

  1. 这种单一的'Polygon'里面出现多个形状, 会出现中空的情况, 类似布尔运算, 这样就可以在地图中描述那种圈型的国家

{"type": "FeatureCollection","features": [{"type": "Feature","properties": {},"geometry": {"type": "Polygon","coordinates": [[[-39.7265625,-3.162455530237848],[127.96875,-3.162455530237848],[127.96875,74.1160468394894],[-39.7265625,74.1160468394894],[-39.7265625,-3.162455530237848]],[[-22.5,15.961329081596647],[110.74218749999999,15.961329081596647],[110.74218749999999,70.8446726342528],[-22.5,70.8446726342528],[-22.5,15.961329081596647]]]}}]
}

效果如下:

8. 描述多个面(MultiPolygon)
优势:

  1. 写法简洁

  2. 这些点样式可以共用

{"type": "FeatureCollection","features": [{"type": "Feature","properties": {},"geometry": {"type": "MultiPolygon","coordinates": [[[[-39.7265625,-3.162455530237848],[127.96875,-3.162455530237848],[127.96875,74.1160468394894],[-39.7265625,74.1160468394894],[-39.7265625,-3.162455530237848]]],[[[-22.5,15.961329081596647],[110.74218749999999,15.961329081596647],[110.74218749999999,70.8446726342528],[-22.5,70.8446726342528],[-22.5,15.961329081596647]]]]}}]
}

这里如果重叠了就是颜色的叠加了如图所示:

9. 描述一个组(geometries)

  1. 比如我们为了表示一种特定的地貌那么我们可以把这个地貌数据独立起来

{"type": "FeatureCollection","features": [{ // 可以包括点线面, 一个独立的集合"type": "GeometryCollection","geometries": [{"type": "Point","coordinates": [108.62, 31.02819]}, {"type": "LineString","coordinates": [[108.896484375, 30.1071178870],[108.2184375, 30.91717870],[109.5184375, 31.2175780]]}]}]}

10. 不同的样式(properties)

{"type": "FeatureCollection","features": [{"type": "Feature","properties": { // 专门放属性"stroke": "#fa9661", // 外边颜色"stroke-width": 4.1, // 外边宽"stroke-opacity": 0.7, // 外边透明度"fill": "#9e290c",  // 填充色"fill-opacity": 0.7 // 填充色透明度},"geometry": {"type": "Point",  // 画点"coordinates": [105.380859375, 31.57853542647338]}},]
}

六. geojson的相关网站与工具的使用

** 展示干巴巴的数据大家看着不起劲, 这里我推荐一个绘制geojson的超棒网站地址

那么我来介绍一下如何使用这个网站高效的生成, 以及调试geojson

  1. 也就是最后生成的geojson, 这里的变化可以实时影响图像, 并且会有错误提示很方便编写.

  2. 绘制直线

  3. 绘制多边形也就是面, 这里注意要首位相连.

  4. 绘制矩形, 这里应该是专门封装的方法绘制矩形.

  5. 绘制点, 这里会为我们在地图上mark一下, 具体的图片需要我们自己在项目中引用.

image
  1. 点击之后进入编辑模式, 鼠标在图形上会出现小手标识, 此时可以拖动图形移动, 操作可以选择是否保留.

  2. 删除模式, 点击可以删除指定图形,操作可以选择是否保留.


单击图形可以出现如图所示的操作框.

  1. 添加样式属性, 上方展示的是当前样式属性

  2. 保存你的更改

  3. 删除这个图形

image
  1. 点击open可以使用本地的geojson文件进行导入绘制.

  2. save下面点击geojson可以把生成的代码文件下载到本地.

七.自制geojson解析绘制工具的思路

  1. 我们可以只做一个转换器, 也就是你随便写认为不错的格式, 最后转换成geojson的格式.

  2. 直接用你喜欢的格式来绘制图形

  3. 如果用canvas来实现就是绘制对应的图形就好了, 就是图形叠加那里需要特殊处理一下, 样式直接读取properties里面的数据进行设置.

  4. 绘制经纬度也是个问题, 毕竟在平面上不好计算经纬度(接下地图绘制章节会讲相关知识).

  5. 所以综上看来是不是绘制一张平面版的地图也没那么困难, 只要数据对了就成功一小半了.

八.地图的基本概念 (瓦片地图, 矢量地图)

** 有没有发现咱们使用的地图在放大的时候,区域都是一个方块一个方块的被加载成图像的.
** 如果你打开控制台的network还可以看到有好多png的请求.
** 地图这种超大的数据, 超多细节是如何做到快速渲染的?
** 下面是现在比较主流的两种地图的绘制模式.

栅格瓦片地图

顾名思义图片像是瓦片一样堆叠起来的格子状成为地图, 有点像拼图, 是不是感觉一点也不高大上....
但这里也是有很多问题要解决的, 比如你在俯视世界的视角看地图, 那么出现的就是世界的瓦片图片, 当高度小于一定的数值时就采用另一套相应的瓦片, 在某个高度范围内是采用放大瓦片图片的方式模拟视野的下降, 每次请求瓦片图片都需要传递: 1: 当前视口所在坐标(经纬度) 2: 当前视口宽高 3: 当前视角高度.

栅格瓦片以 256 256 或 512 512 大小的图片为介质,这种技术通常是在服务端预先将图片渲染好,前端根据地图的缩放等级,按需加载图片加以拼接,目前依旧在大规模使用,但这种方式存在一些劣势:

受到网络带宽开销和存储空间限制的影响大,离线化部署成本高,单套主题将近 500 多 G(中国)。
样式编辑完后端渲染需要时间长。
无三维的建筑数据,在 3D 场景中无高度信息。
数据保密性差。

矢量地图

顾名思义就是矢量绘制出图形, 只要不是照片肯定会小很多, 对于矢量为什么轻量并且不失真可以参考的上篇文章svg的分享svg实战

矢量瓦片采用和栅格瓦片相同的分级切割方案,不同的是,瓦片数据传输的是地理数据,包括道路、土地、建筑等,通过在前端做地图的渲染,具有如下优势:

极少占用服务器空间,降低网络开销,本地化部署只需5G空间(中国)。
地图的底图样式更换简单.
因为具有了地理数据本身,可在数据基础上做三维空间的延伸,例如 3D 建筑。
数据保密性强。

九.不同的坐标系

** 地球本身是个椭球体, 要把它以平面的方式绘制在一个矩形上也真的不好办, 现在有不少绘制的方式但是都有各自的优缺点, 感兴趣的朋友可以查查看具体的细节, 我这里就简单介绍下比较常见的方式.

  1. 经纬度EPSG:4326 也就是地图的默认坐标
    现在球体上定义好经纬度, 然后在正方形纸上画出刻度, 对应的绘制

  2. 墨卡托投影(EPSG:3785 )
    把地球放在一个圆筒里面, 假设地球内部有个光源, 那么地球在圆柱上的投影就是地图

  3. 火星坐标系

火星坐标是国家测绘局为了国家安全在原始坐标的基础上进行偏移得到的坐标,基本国内的电子地图、导航设备都是采用的这一坐标系或在这一坐标的基础上进行二次加密得到的。
火星坐标的真实名称应该是 GCJ-02 坐标,基本上所有的国内的电子地图采用的都是火星坐标系甚至 Google 地图中国部分都特意为中国政府做了偏移。

  1. 百度坐标系

火星坐标是在国际标准坐标 WGS-84 上进行的一次加密,由于国内的电子地图都要至少使用火星坐标进行一次加密,百度直接就任性一些,直接自己又研究了一套加密算法,来了个 二次加密,这就是我们所熟知的百度坐标 BD-09,当然只有百度地图使用的是百度坐标

  1. WGS-84 坐标系

GS-84 坐标是一个国际的标准,一般卫星导航,原始的 GPS 设备中的数据都是采用这一坐标系。国外的 GoogleMap、OpenStreetMap、MapBox、OpenLayer 等采用的都是这一坐标。

geojson设置坐标系
由于坐标系的不同, 那么就算绘制一个点的坐标也都不会完全相同了, 那么就需要我们来告诉使用geojson的人按哪种坐标系进行解析

{"type": "FeatureCollection","crs": { // 定义坐标系 (如果不写就是使用经纬度的坐标系)   默认为EPSG:4326。"type": "name", // "type" 和 "properties"。为强制拥有"properties": {"name": "urn: ogc: def: crs: EPSG: 54013" // 这里定义具体的规则}},"features": [{},]
}

使用上线的规则

{"type": "FeatureCollection","crs": {"type": "link", // 这里变成了link"properties": {"href": "http://example.com/crs/42", // 这里是你设置的资源链接"type": "proj4" // "proj4","ogcwkt",esriwkt" 只能这三种格式}},"features": [{},]
}

十.更快的前端数据 -> WebAssembly

**WebAssembly是一种新的编码方式,文件体积更小,启动速度更快,运行速度也更快,与使用JavaScript构建的Web应用相比,性能提升明显。它是多种编程语言的编译器目标,包括C++、C、Rust等。
WebAssembly 是由主流浏览器厂商组成的 W3C 社区团体 制定的一个新的规范。**

WebAssembly 可以明显的提升计算的速率, 还挺适合用在地图库里面的

  1. WebAssembly 和 JavaScript 结合使用, 短时间并不会替代js

  2. .wasm文件结尾的文件来标识.

  3. WebAssembly 有一套完整的语义,实际上 wasm 是体积小且加载快的二进制格式, 其目标就是充分发挥硬件能力以达到原生执行效率
    WebAssembly 运行在一个沙箱化的执行环境中,甚至可以在现有的 JavaScript 虚拟机中实现。在web环境中,WebAssembly将会严格遵守同源策略以及浏览器安全策略。
    WebAssembly 设计了一个非常规整的文本格式用来、调试、测试、实验、优化、学习、教学或者编写程序。可以以这种文本格式在web页面上查看wasm模块的源码。
    WebAssembly 在 web 中被设计成无版本、特性可测试、向后兼容的。WebAssembly 可以被 JavaScript 调用,进入 JavaScript 上下文,也可以像 Web API 一样调用浏览器的功能。当然,WebAssembly 不仅可以运行在浏览器上,也可以运行在非web环境下。

  4. 解析 - 解码 WebAssembly 比解析 JavaScript 要快

编译和优化 - 编译和优化所需的时间较少,因为在将文件推送到服务器之前已经进行了更多优化,JavaScript 需要为动态类型多次编译代码
重新优化 - WebAssembly 代码不需要重新优化,因为编译器有足够的信息可以在第一次运行时获得正确的代码
执行 - 执行可以更快,WebAssembly 指令更接近机器码
垃圾回收 - 目前 WebAssembly 不直接支持垃圾回收,垃圾回收都是手动控制的,所以比自动垃圾回收效率更高。目前浏览器中的 MVP(最小化可行产品) 已经很快了。在接下来的几年里,随着浏览器的发展和新功能的增加,它将在未来几年内变得更快。

说了这些都是概念, 接下来我们就一起实战一下go

十一. hello 级别的WebAssembly

中文官网
官网的实现还需要配置环境啥的搞得很正式, 入门级别其实我们更想的是尝尝鲜, 只要你会点c++就能用我接下来的方法实现.

在线生成
在线生成

image
  1. 点击转换c++代码为WebAssembly格式

  2. 点击下载转换好的文件

  3. 下载到的是个二进制文件

引用文件

 fetch("/test.wasm").then((res) => res.arrayBuffer()) // 拿到Buffer格式.then((bytes) => WebAssembly.compile(bytes)) // 转字节码.then((mod) => {const instance = new WebAssembly.Instance(mod);const exp = instance.exports;console.log(exp._Z7showNumv())});
  1. exp._Z7showNumv 而不是 exp.showNum, 这个我们可以在Wat那一栏修改一下, 但是代码多了修改起来也不容易应该有禁止转换时修改名称的选项这里就不过多展开了.

  2. 注意这里会跨域, 因为属于文件协议, 你可以本地启个服务.

开发成本

  1. 需要的不只是前端技术了.

  2. bug稍微有点多, 比如不好调试, 还有的同学遇到了每次编译结果不同等问题.

  3. 社区不完善

  4. 建议这门技术先使用在封装度较高, 计算量很大的模块上.

十二.(组内篇)我写的2d与3d工程的代码介绍

这里我在组内展示一下我编写的两个项目的代码结构与遇到的问题, 就不在这里展开了毕竟涉及保密问题, 但大体思路就是把地图分成世界, 国家, 省, 市, 区 几个等级(省市区是中国的分法), 相当于一个状态机, 然后在每个状态下做相应的事比如打点与连线, 每次变换图层状态都会隐藏其他图层展示相应视野的图层.

end.

地图方面也属于前端比较有用的一环, 我今年刚接触地图相关项目也是一脸蒙, 但是详细学习了geojson等知识之后再用地图相关组件库就非常顺畅了.
这次就是这样, 希望和你一起进步.

关于本文:

来源:lulu_up

https://segmentfault.com/a/1190000037611134

最后

欢迎关注【前端瓶子君】✿✿ヽ(°▽°)ノ✿

回复「算法」,加入前端编程源码算法群,每日一道面试题(工作日),第二天瓶子君都会很认真的解答哟!

回复「交流」,吹吹水、聊聊技术、吐吐槽!

回复「阅读」,每日刷刷高质量好文!

如果这篇文章对你有帮助,「在看」是最大的支持

》》面试官也在看的算法资料《《

“在看和转发”就是最大的支持

记一次前端揭开绘制地图的神秘面纱分享会相关推荐

  1. 揭开前端绘制地图的神秘面纱

    点击上方关注 前端技术江湖,一起学习,天天进步 记录了我在组内的技术分享, 有同样需求的同学可以参考一下 分享全程下来时间大约 70分钟 一. 为什么要分享前端相关的"地图"知识 ...

  2. .net单点登录demo_图文并茂,为你揭开“单点登录“的神秘面纱

    本文首发于政采云前端团队博客:图文并茂,为你揭开"单点登录"的神秘面纱 https://www.zoo.team/article/sso 概念 单点登录( Single Sign ...

  3. 揭开均线系统的神秘面纱_在应用程式审查API中揭开新玩法的神秘面纱

    揭开均线系统的神秘面纱 During the #11WeeksOfAndroid the new Play In-App Review API was announced. This was a lo ...

  4. html5实现单点登录,图文并茂,为你揭开“单点登录“的神秘面纱

    概念 单点登录( Single Sign On ,简称 SSO),是目前比较流行的企业业务整合的解决方案之一,用于多个应用系统间,用户只需要登录一次就可以访问所有相互信任的应用系统. 前置介绍 同源策 ...

  5. 揭开人类语言的神秘面纱:从理解到处理自然语言

    https://www.toutiao.com/a6709740042509615619/ 随着人工智能的进步和技术变得越来越复杂,我们希望现有的概念能够接受这种变化或者改变自己.同样,在自然语言的计 ...

  6. 揭开webRTC媒体服务器的神秘面纱——WebRTC媒体服务器开源项目介绍

    揭开webRTC媒体服务器的神秘面纱--WebRTC媒体服务器&开源项目介绍 WebRTC生态系统是非常庞大的.当我第一次尝试理解WebRTC时,网络资源之多让人难以置信.本文针对webRTC ...

  7. 揭开Java 泛型类型擦除神秘面纱

    转载自   揭开Java 泛型类型擦除神秘面纱 泛型,一个孤独的守门者. 大家可能会有疑问,我为什么叫做泛型是一个守门者.这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘 ...

  8. @程序员,为你揭开直播技术的神秘面纱!

    作者 | 阿文,责编 | 郭芮 头图 | CSDN 下载自视觉中国 出品 | CSDN(ID:CSDNnews) 随着Web 2.0 的普及以及移动互联网技术的发展,各种视频分享.流媒体直播类型的服务 ...

  9. 小编带你一起揭开DLL木马的神秘面纱(转)

    在这个万"马"奔腾的时代,网络上充斥着各种各样的木马,不过随着杀毒技术的进步和大家防毒意识的提高,传统木马已渐渐失去市场,而DLL木马则"与时俱进"以其强大的生 ...

最新文章

  1. swift3.0最新拨打电话方法
  2. axis1 web Service 环境部署
  3. Servlet--生命周期
  4. 错误处理:安装torch-sparse、torch-spline、torch-scatter、torch-cluster
  5. Hadoop(MapR)分布式安装及自动化脚本配置
  6. CRM BP attachment read debug
  7. Oracle数据库之数据类型
  8. linux中mysql基本操作
  9. 《王道计算机考研》:应用层
  10. ElasticSearch IK配置同义词
  11. PID参数整定一些总结
  12. 企业邮箱怎么收发邮件,怎么保护公司邮件安全?
  13. 提示https不安全的原因及解决办法
  14. 未能加载文件或程序集“Microsoft.Web.Infrastructure”
  15. 构建共线矩阵的两种惊艳操作
  16. Cannot open url. please check this url is correct
  17. RK3588快速上手 | 01-RK3588开发板快速上手
  18. Spans,一个强大的概念
  19. 【Blender】问题记录001--用grease pencil画线条时一节一节不连贯的原因
  20. 在10万以内的一个整数,它加上 100 后是一个完全平方数,再加上 168 又是一个完全平方数,请问该数是多少?

热门文章

  1. 文献分析-基于AI的文献分析工具
  2. 工作流+口才思维导图模板
  3. chatgpt赋能python:PythonSh-一个强大的Shell命令助手
  4. Excel | 基因名都被Excel篡改了怎么办呢!?~(附3种解决方案)
  5. OpenGauss线程管理-主线程-Postmaster(1)
  6. Python自动化办公word、ppt转pdf
  7. python中使用matplotlib库绘制多个子图(subplot函数用法)
  8. 彻底解决matplotlib中文乱码问题
  9. ChatGPT 革命性读书方法已被证明是一种非常有效和高效的学习和吸收新信息的方法
  10. pandas在数据分析(异常值识别问题)中的应用,以衍生特征计算为例(含2022年全国服务外包大赛实例)