前端开发大屏地图?必知必会的基本知识


theme: Chinese-red
highlight: monokai

本文为稀土掘金技术社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究!

📖阅读本文,你将

浅度地了解前端开发大屏地图必备知识点:

  • 投影 & 坐标系
  • 地图瓦片
  • GeoJSON
  • turf.js

文章大纲

一、为什么大多数的大屏都有 地图

智慧城市、态势感知、指挥调度中心、作战平台、驾驶舱、管控中心、城市大脑…

无论这些大屏都给自己取了多么炫酷的名称,都难以掩盖它们相似、相同的本质:讲故事 。这一点在本专栏的第一篇中已有细述,暂不赘述。但它们另一个相似点你一定也发现了:

它们似乎大多数都在中间放着一张地图。

对,就像上面这样。

但是,为什么呢?

围绕着 讲故事 的主旨,我们不难发现,描述一件事最最合理的方式应该是这样的:

谁 在什么时间、在哪里、做了一件什么事情。

对于一个系统而言,也就是能知道哪个用户、哪个终端,在什么时间、什么物理位置上,触发了什么事件。

这里有几个要素:

  • 对象主体 (人、设备、道路等)
  • 事件时间
  • 事件位置
  • 事件信息

其中 “主体”、”时间”、”事件” 都属于易于描述的内容:

张三、12月22日,触发了烟雾报警。

但唯独 事件位置 难以描述,要么一串地理文本冗长不直观、要么关键信息缺失,都比不上一张地图,明明白白地将他触发报警的位置放上一个项目的 icon 来得直观。

这也正是为什么在各种 故事 中,数字孪生 这个概念被不断提及的原因之一。

故事要想动人,那它首先就得直观易懂。

这就是大屏上地图的核心意义。

二、前端人员开发地图是专业的吗?

先说结论:太不专业了。

因为地图开发(也被称为 GIS 开发),本来就是一门自成体系的学科。

GIS 开发 独立于 “前端开发”、“后端开发” 之外,一个独立的开发体系了,相关招聘和技术栈也和单纯的前端开发有了较大的出入。

相关的工具体系,比如 arcGisarcMap 等等,咱普通小前端也通常不太熟。

至于 .shp.shx 等这些格式的地理数据,前端更是一头雾水。

但目前很多项目上,对于前端的要求偏偏是:

不仅能开发管理后台、H5、小程序,还得会大屏开发,而且还得会:

地图开发。

业余人士和专业人士拼专业程度是不可能的。

但,躺平 不可取,躺赢 不可能。

该了解的基本知识还是得了解的。

三、投影方式和坐标系

当我们试图在页面上加载地图时,我们通常不是从 0 开始的,而是会选择一款地图引擎。

  • 百度、高德、谷歌 等
  • leaflet、OpenLayers 等
  • mapbox、cesium 等

但它们在展示地图时,有两个核心概念,分别是 投影方式坐标系

3.1 投影方式 (Projection)

目前 web Gis 最常用的 投影方式墨卡托投影,常规的地图厂商和地图引擎,都默认使用的这类投影方式。

墨卡托投影的核心思路是,先把球形地图展开成柱状图,然后平铺成平面。

但是众所周知,球形是不可能铺成圆柱形的,因此,摩卡托投影是存在地形扭曲的,尤其是越靠近南北极的地理面积就越是比真实面积显示要大。

对于这块知识,了解即可,一般情况下不会需要去进行投影方式变换。

3.2 坐标系

目前国际上最通用的经纬度坐标系,来自于 “美国国家地理空间情报局” 出台的 WGS84

世界大地测量系统(英语:World Geodetic System, WGS),WGS包含一套地球的标准经纬坐标系、一个用于计算原始海拔数据的参考椭球体,和一套用以定义海平面高度的引力等势面数据。

但是,国内通用的地图厂商,通常不被允许直接使用 WGS84 进行地理信息服务。

你问为什么?当然是国家安全,数据安全啊。

国测局规定:

国内出版的各种地图系统,必须⾄少采⽤ GCJ-02 对地理位置进⾏⾸次加密的坐标系。

GCJ-02 也被称为 国测局坐标系。除此之外,它还有个经常被拿来戏称的 火星坐标系 的外号。

  • ⾼德和Google在国内都是使⽤ GCJ-02 坐标系
  • 百度使⽤的是在 GCJ-02 基础上再⼀次加密的 BD-09 坐标系。

目前,社区里也是有很多关于 GCJ-02 坐标系的坐标和 WGS84 坐标互相转换的算法,最广受认可的是这个:coordtransform

四、地图瓦片

地图上要展现出丰富的信息,显示街道、显示桥梁、显示房屋、显示湖泊……要支持缩小、支持放大,就必须有一个信息载体,这个载体,也被称为:

地图瓦片

我们肉眼看上去一整片的地图,程序在处理时,实际上是把 切成了 它们

若干块可描述的矩形拼凑起来,就成了我们能看到的一整张效果图。

因此,我们在显示地图时,经常发现地表信息是一块一块显示出来的。

那么,这种一块一块的地图瓦片,是用的什么技术呢?

目前主流的思路分两种:

  1. 矢量瓦片 (Raster Tile)
  2. 栅格瓦片 (Vector Tile)

传统栅格瓦片,它的思想是通过栅格化的图片(png/jpg等)来进行地理数据的显示。

它无法直接表达一条高速公路。但若干张简单的 png 拼凑却能让你快速看到整个北京的地理信息。

矢量瓦片,它的思想,就是将各种地理信息矢量化,最终通过 字体、线段、图表、风格、矢量数据 等信息,将地理信息保存下来,最终完成到地图上的渲染。

比如我想记录一条高速公路,那我就把这条高速公路的宽度、矢量信息等保存下来,后续可以支持它在地图上进行渲染。

矢量瓦片 的体积更小、定制化能力更强,是目前主流地图厂商使用的瓦片提供方式。

栅格瓦片 的优势在于它对终端的性能要求低,且简单易懂,易于上手。

那么我们应该如何选择地图所使用的瓦片呢?

我给出一套简单的选择瓦片的思路:

  • 如果你需要数据绝对免费,且可能考虑私有部署,那选 栅格瓦片

    目前 “国家地理信息公共服务平台” 提供的 “天地图” 是完全免费,且可以通过爬取手段轻易完成私有化部署的。

  • 如果你的甲方考虑购买商用服务,且没有私有化部署的场景,大胆选择 矢量瓦片

    比如 baidu、高德、mapbox 等提供的定制化商用瓦片服务,基本都是矢量的,体验非常好,而且没啥接入成本。

没有完美的方案,只有完美的场景适配,毕竟最后是以甲方满意和项目交付作为目标的。

五、 GeoJSON: web 端的地理信息通用货

只有 “瓦片”,可能还无法满足甲方的全部需求。

甲方:把这个湖泊高亮一下,水面要发光,要五彩斑斓。

甲方:我的三个项目,你把它们框起来,用特别的颜色标识出来。

甲方:把工人都给我显示在地图上。

业务场景对地图的要求绝对不是仅仅把地图渲染出来,核心的逻辑还是在地图上 做一些事情,显示一些业务

因此,除了能把地图显示出来,我们还需要 把业务显示出来

那么,如何描述业务地理信息呢?

答案是:GeoJSON!

5.1 什么是 GeoJSON ?

GeoJSON 是一种数据格式。它被用来描述地理数据。

其典型格式如下:

{
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [125.6, 10.1]
  },
  "properties": {
    "name": "Dinagat Islands"
  }
}

目前最新的 GeoJSON 格式支持以下类别的地理信息(Feature)描述:

  • 点: Point
  • 点组(多个点): MultiPoint
  • 线: LineString
  • 线组(多条线): MultiLineString
  • 多边形: Polygon
  • 多边形组(多个多边形): MultiPolygon

以及:

  • 包含一组上述Feature的集合:FeatureCollection

GeoJSON 格式官方网站:https://www.rfc-editor.org/rfc/rfc7946

5.2 理解 Feature 的格式

如果我想在地图上点一个点:

就需要用到 Feature 类别的 GeoJSON 数据,通常长这样:

{
  "type": "Feature",
  "properties": {
    "id": 1,
    "name": "摸鱼的春哥"
  },
  "geometry": {
    "coordinates": [
      114.48328003261895,
      29.35629560547187
    ],
    "type": "Point"
  }
}

注意,以上格式,分为三部分:

  • type:类别,支持的值只有: FeatureFeatureCollection
  • properties:属性,用来记录业务属性,如 idname 等。
  • geometry:几何信息。用来表示图形信息,是点还是线还是多边形,它们的经纬度是多少。

FeatureCollection 则可以表达多个 Feature 的集合:

内容如下:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "coordinates": [
          114.48328003261895,
          29.35629560547187
        ],
        "type": "Point"
      }
    },
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "coordinates": [
          [
            [
              114.58791284766971,
              29.391982262865895
            ],
            [
              114.58791284766971,
              29.2928121036324
            ],
            [
              114.72107020435487,
              29.2928121036324
            ],
            [
              114.72107020435487,
              29.391982262865895
            ],
            [
              114.58791284766971,
              29.391982262865895
            ]
          ]
        ],
        "type": "Polygon"
      }
    }
  ]
}

完成了对 一个点 + 一个多边形 地理信息的描述。

六、turf.js:前端必备的地理工具

浏览器和 Node.js 端的地理信息分析工具。 —— turf.js 官网。

官网地址:http://turfjs.org/

为什么我们会需要这样一个工具?

因为:

关于地理信息的几何计算,它是专业的。

6.1 场景:求几个重心(放文本或者定位)

假设场景:你有一个多边形 GeoJSON 数据,现在你想知道它的 几何重心 在哪里?

除了自己慢慢写数学公式造轮子,turf.js 可能是更好的选择:

const polygon = {
  "type": "Feature",
  "properties": {},
  "geometry": {
    "coordinates": [
      [
        [-81, 41],
        [-88, 36],
        [-84, 31],
        [-80, 33],
        [-77, 39],
        [-81, 41]
      ]
    ],
    "type": "Polygon"
  }
}
var centroid = turf.centroid(polygon);

6.2 场景:求面积

甲方:算一下,我们这个区域有多少万平方公里。

使用代码:

const polygon = {
  "type": "Feature",
  "properties": {},
  "geometry": {
    "coordinates": [
      [
        [-81, 41],
        [-88, 36],
        [-84, 31],
        [-80, 33],
        [-77, 39],
        [-81, 41]
      ]
    ],
    "type": "Polygon"
  }
}
var area = turf.area(polygon);// 一键计算出面积

是不是很简单?
是不是很实用?

6.3 更多场景

它还能支持哪些场景的能力?

那可太多了:

  • alone: 延长某条线 xx 距离,得到一个点。
  • bbox: 将一个(组) GeoJSON 数据的矩形范围计算出来。(通常用在地图缩放上)
  • bearing: 计算出一条线和正北方向的夹角(顺时针)。
  • distance: 两点之间的直线距离
    等等等等……

具体的功能清单,还需要自行去官网感受理解。你会感受到它的强大和魅力的。

七、总结

通过本文的学习,相信你对大屏地图开发的前置理论知识已经有了一个大致的了解。

下一节,我们将借助 mapbox-glmaplibre-gl 地图引擎,进行两种常见业务场景地图的实际开发。

© 版权声明
THE END
喜欢就支持一下吧
点赞5 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容