本篇使用Mapbox GL JS实现数据的热力图可视化,以截止到2020-03-01日的新冠疫情作为示例数据。
热力图使用颜色的深浅表示数值的变化,从而表示数据的分布情况,这使得用户可以更容易的理解复杂的数据分布,发现其中的规律。形象地说,热力图展示了数据的“重点”,因此在数据可视化中被广泛应用。
1 引入js
文件
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.1.1/mapbox-gl.js'>script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.1.1/mapbox-gl.css' rel='stylesheet' />
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js">script>
2 构建地图容器
<div id='map'>div>
3 初始化Mapbox GL地图对象
mapboxgl.accessToken = 'your token';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/dark-v9',
center: [-74.50, 40],
zoom: 9
});
4 定义样式
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
5 效果
1 数据示例
{
"geometry": {
"coordinates": [
114.3,
30.5955
],
"type": "Point"
},
"type": "Feature",
"properties": {
"new_recovery": 1,
"new_death": 0,
"new_diagnosis": 0
}
}
2 添加数据源
map.addSource('virus-source', {
"type": "geojson",
"data": "data.json"
});
3 添加热力图图层
map.addLayer(
{
id: "virus-heatmap",
type: "heatmap",
source: "virus-source",
maxzoom: 7,
layout: {
visibility: "visible"
},
paint: {
}
}
);
4 效果
很明显,这幅图的效果十分不好,首先,其存在着严重的“热力失真”现象,在地图缩放级别很小的情况下,中国的整个东边都好像被感染了,这明显是不符合现实情况的;再者,如果在不同的地图缩放等级下,均采用相同的热力半径,会导致更严重的可视化失衡,因此我们需要进一步改善。
在改善之前,有必要介绍Mapbox强大的Expression
表达式语言,它被用于定义地图样式内的layout
属性、paint
属性或filter
属性的值,允许使用多个属性对数据进行样式的配置,同时可以应用条件、数学、逻辑和字符串操作符对数据进行操作,十分强大。
1 normal expression
['*', ['pi'], ['^', 3, 2]]
:表示3^2 * pi。
2 property expression
['-', 2017, ['number', ['get', 'Constructi'], 2017]]
:表示2017 - number of Construction
3 zoom expression
用于使地图的样式随地图的缩放级别而改变,缩放表达式可以用来控制数据密度。
[
'interpolate', ['linear'], ['zoom'],
10, ['/', ['-', 2017, ['number', ['get', 'Constructi'], 2017]], 30],
13, ['/', ['-', 2017, ['number', ['get', 'Constructi'], 2017]], 10],
]
Mapbox GL热力图具有三个主要paint
样式属性。
1 heatmap-radius
该属性用于设置热力图中每个点的“影响半径”(相当于核密度可视化中的带宽参数),该值越高,外观就会更平滑,详细程度也更低。该属性也可以是一个缩放函数,允许在缩放时调整外观。在实际可视化中,常设置为与缩放级别相关。
2 heatmap-weight
该属性用于定义热力图中某点对热力图贡献的权重,在实际可视化中,常设置为与属性值相关。
3 heatmap-intensity
该属性用于在全局范围内调整热力图外观的强度,值越高,每个点对外观的影响就越大。这种关系是线性的。例如,将heatmap-intensity
设置为10.0
相当于重复绘制默认值1.0
的数据集十次。在实际可视化中,常设置为与缩放级别相关,缩放级别越高,该值应越大,以减少热力失真。
4 heatmap-color
该属性用于定义热力图中最重要的属性-颜色,在实际可视化中,常设置为与热力图密度相关。
5 heatmap-opacity
该属性用于定义热力图的透明度。
6 改进
参考网站https://www.mapbox.cn/coronavirusmap/,修改配色,代码如下。
map.addLayer(
{
id: "virus-heatmap",
type: "heatmap",
source: "virus-source",
paint: {
// 使用new_diagnosis属性
"heatmap-weight": [
"interpolate",
["linear"],
["get", "new_diagnosis"],
0,
0,
1000,
1
],
"heatmap-intensity": [
"interpolate",
["linear"],
["zoom"],
0,
3,
9,
5
],
// Color ramp for heatmap. Domain is 0 (low) to 1 (high).
// Begin color ramp at 0-stop with a 0-transparancy color
// to create a blur-like effect.
"heatmap-color": [
"interpolate",
["linear"],
["heatmap-density"],
0,
"rgba(0, 0, 0, 0)",
0.1,
"#927903",
0.15,
"#ffd403",
1,
"red"
],
// Adjust the heatmap radius by zoom level
"heatmap-radius": [
"interpolate",
["linear"],
["zoom"],
0,
2,
1,
4,
2,
8,
3,
16,
4,
32,
5,
64,
6,
128,
7,
256,
8,
512,
9,
1024
],
// Transition from heatmap to circle layer by zoom level
"heatmap-opacity": [
"interpolate",
["linear"],
["zoom"],
5,
0.95,
6,
0
]
}
}
);
代码+数据:@GitHub
微信公众号:林木菌
若有任何问题,欢迎留言交流。