卫星热力图

概述

为了实现热力图,但又不仅仅是热力图,希望可以放大后看到实际的街景,遂尝试开发,并作出如下效果

这两个版本可自由切换

可以放大至街景

甚至可以进一步进入街景模式

尝试

寻找能够制作热力图的报表或者 API ,先后尝试过Data X、Quick bi、Power bi、Superset、Google API。其中 Superset 可以完成这个需求,并且操作也很简单,只需要将数据的经纬度导入到报表中即可,但放大后有点糊,,,或许也不是有点,遂放弃。最终发现Google API可以完成我的需求,唯一的缺点就是,当我尝试获得 API 也就是 Google 的 GOOGLE_MAPS_API_KEY 时发现需要绑定外国银行卡,否则无法获取,这个小伙伴们要自己想办法啦。

Maps JavaScript API 官方开发文档

静态网页

下面为极简版本,经纬度为随机生成(GOOGLE_MAPS_API_KEY这个小伙伴们自己要申请的)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>卫星热力图</title>
<style>#map { height: 1000px; width: 100%; }</style>
</head>
<body>
<div id="map"></div>
<script>
function initMap() {
const map = new google.maps.Map(document.getElementById('map'), {
zoom: 13,
center: { lat: 38.469044, lng: -90.7623135 }
});
const points = Array.from({ length: 1000 }, () => ({
lat: 38.469044 + (Math.random() - 0.5) * 0.09,
lng: -90.7623135 + (Math.random() - 0.5) * 0.09
}));
new google.maps.visualization.HeatmapLayer({
data: points.map(p => new google.maps.LatLng(p.lat, p.lng)),
map: map
});
}

function loadScript() {
const script = document.createElement('script');
script.src = `https://maps.googleapis.com/maps/api/js?key=GOOGLE_MAPS_API_KEY&callback=initMap&libraries=visualization`;
script.async = true; script.defer = true;
document.head.appendChild(script);
}

document.addEventListener("DOMContentLoaded", loadScript);
</script>
</body>
</html>

效果图为

此版本因为数据都是随机生成,当然也可以换成固定的,不需要从数据库中读取。所以直接部署在GitHub即可,直接把代码扔到GitHub中,然后部署完后,就会生成一个网址。(GitHub Pages允许免费部署一定数量的静态网页)

Quickstart for GitHub Pages

大家也可自行上网查找如何将代码部署在GitHub上。

ps:就是将上面的代码,GOOGLE_MAPS_API_KEY替换成自己的,然后将代码放进一个html文件,再去Settings设置下就完成了

动态网页

此本版数据来自数据库,需要服务器来部署node.js,在这里我使用的是Vercel来免费部署网站(非常喜欢这个vercel,我的这个博客也是部署在上面的)。Vercel可以跟Github联动,支持直接从Github上同步项目,然后进行部署,非常方便。

这里我认为最麻烦的就是vercel的配置文件与文件目录,这个好像比较严格?稍有不对便会报错。

其中package.json的代码为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
"name": "express",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node api/index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@vercel/postgres": "^0.7.2",
"dotenv": "^16.4.1",
"express": "^4.18.2",
"cors": "^2.8.5",
"pg": "^8.11.0",
"node-cache": "^5.1.2" ,
"axios": "^1.0.0"

}
}

vercel.json代码:

1
2
3
4
{
"version": 2,
"rewrites": [{ "source": "/(.*)", "destination": "/api" }]
}

大家可根据需要自行修改文件名称,以及依赖。

成果图:

优化升级

我增加了一些额外功能,比如“标记“,鼠标放上去时会显示那里的街景图

但是这个图片并不便宜,每次发起请求获取这张图片需要0.007美元,如果数据一旦多起来,那么每次加载将会消费不少钱。所以我优化成了每次只有当鼠标放上去时才会发起这张图片的请求,并把这个图片写进了数据库,下次在显示这张图片时,将会从我的数据库获取,而不是调取 Google 的 API

结尾语:希望对大家制作热力图有所帮助,有问题可以联系作者。