一张新型肺炎地区分布地图是怎么制作的?

前言

2020年刚开始,各钟不幸的消息满天飞。新型肺炎的蔓延,科比去世… 无时无刻让我感到痛楚。为了不给国家添乱,新年几天都在窝在家里。时不时拿起手机,观察一下现在病情蔓延情况。下面这张地图就是一张典型的GIS应用。

infection-cover-status-demo

每当我看到这张静态图时,很想要知道几个信息无法获知。

  1. 我们能通过颜色和图例比较一个省的确诊人数范围,看不到一个省具体患病人数。
  2. 由于是一张静态图,我们没法获市级数据。如果地图可以拖动,放大缩小就简单多了。
  3. 每次看到红色,心里都很焦虑。能换成其他颜色,我自己更加能接受点。

基于这两个小功能,我准备介绍一下怎么去制作一张地图。我准备分两个阶段来做介绍。

  1. 先用最简洁的代码来生成一张静态图片。通过这个阶段,让我们认识一下一般地图应用开发的流程。
  2. 当我们了解流程以后,我们就把这个程序改造成地图服务,让她和知名的地图前端库Leaflet合并开发一个可交互的地图,集成点有趣的功能。

这篇文章,我准备先从制作一张静态图片开始。

让我们从环境开始

以前开发地图应用软件,可能需要掌握很多编程语言技能,才能胜任一个完整的项目。比如一个典型的GIS B/S应用一般会使用Java, C#或其他后端编程语言来开发后端,然后用JavaScript + HTML来开发前端展现。

今天用我们熟悉的JavaScript;即使是前端开发人员也可以开发后端地图应用了。追求极简开发环境的话,我们只需要2个工具。Node.js (推荐8以上,或者直接安装最新版本都是兼容的)和 vscode.

这篇文章照顾新手,写的比较多。老鸟请自行过滤。勿喷。

创建工程,添加引用

接着,我们创建一个工程目录。用以下命令就可以了。(我个人比较喜欢使用命令行,由于平时都是用macOS做日常使用机器。所以以下命令行都是macOS执行验证的)。

# 创建项目目录
cd [your workspace]
md nCoV-map
cd nCoV-map

# 创建功能,添加引用
npm init -y
npm i --save ginkgoch-map canvas lodash

# 新建一个文件,这个将是我们写代码的地方
touch tutorial-01.js

这里引用了canvas库,是因为Node.js没有提供绘图API,我们只能引用一个第三方Node.js库来替代使用。

到这里,我们的工程已经建立好了。

GIS数据

GIS应用里面数据是很重要的。我把她分为静态数据和动态数据。静态数据就是我们的几何图形以及她们特定的特征数据。如地区的名字等。动态数据就是我们实时关注的疫情变化。

一般静态数据比较容易找到。百度搜索中国地图数据csv, json, shapefile都可以找到。这个项目里面,我准备使用shapefile作为我的静态数据。这里你可以找到以下数据,我们一会儿会使用到。把上面数据下载下来以后,放到工程的data目录下面。

  • chn/
    • gadm36_CHN_1_3857.shp - 省级数据
    • gadm36_CHN_2_3857.shp - 市级数据
  • cntry02.shp - 世界国家数据

动态数据会麻烦点。我是写了一个爬虫,定时爬取。有兴趣可以私聊。不过作为例子,我放上了几份疫情数据在data/infected目录里面以便做示例。

剩下的工作就很简单了

叠加世界数据

首先,我们定义一个函数来创建一个地图的图层,一个数据源即一个数据图层,多个数据图层叠加起来就可以构成我们期望的样式。使用ginkgoch-map,我们是这样定义一个图层的。

function createLayerWithDefaultStyle(filePath) {
   
    // create a source with the specified shapefile file path
    let source = new GK.ShapefileFeatureSource(path.resolve(__dirname, filePath));

    // wrap the source as a world layer
    let layer = new GK.FeatureLayer(source);

    // set a style on the layer
    layer.styles.push(new GK.FillStyle('#f0f0f0', '#636363', 1));

    return layer;
}

有了layer, 我们可以简单查看我们数据图层的样子。比如对于数据cntry02.shp:

let worldLayer = createLayerWithDefaultStyle('../data/cntry02.shp');
await worldLayer.open();
let worldImage = await worldLayer.thumbnail(512, 512);
fs.writeFileSync(path.resolve(__dirname, './images/tutorial-01-world.png'), worldImage.toBuffer());

我们通过命令行执行下面的语句。我们可以找到图片:

node tutorial-01.js

阅读终点,创作起航,您可以撰写心得或摘录文章要点写篇博文。去创作
  • 14
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ginkgoch

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值