h3热力图
https://observablehq.com/d/31ab0068a4664578 是一个 Observable Notebook 的案例(类似于echarts的一个案例库),展示了如何使用 Mapbox 和 H3(Hexagonal Hierarchical Geospatial Indexing System)来创建热力图。
其中:Mapbox 的 API Token 是 Mapbox 平台的授权凭证,好像不是免费的要付费
生成热力图结合h3使用的代码案例(h3库本质只是把h3索引模式转成GeoJSON数据而已):
import mapboxgl from 'mapbox-gl';
import { h3SetToFeatureCollection } from 'h3-js';
mapboxgl.accessToken = 'your-mapbox-access-token'; // 替换为你的 Mapbox Token
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v11',
center: [116.397389, 39.908860],
zoom: 10
});
// 生成 H3 索引
const h3Indexes = ['81003fffffffffff', '81007fffffffffff']; // 示例 H3 索引
const geojsonData = h3SetToFeatureCollection(h3Indexes, h3Index => ({
value: Math.random() * 10 // 随机权重
}));
// 加载 GeoJSON 数据
map.on('load', () => {
map.addSource('heatmapSource', {
type: 'geojson',
data: geojsonData
});
map.addLayer({
id: 'heatmapLayer',
type: 'heatmap',
source: 'heatmapSource',
paint: {
'heatmap-weight': ['get', 'value'],
'heatmap-color': [
'interpolate',
['linear'],
['heatmap-density'],
0, 'rgba(0,0,255,0)',
0.2, 'royalblue',
0.4, 'cyan',
0.6, 'lime',
0.8, 'yellow',
1, 'red'
],
'heatmap-radius': ['interpolate', ['linear'], ['zoom'], 0, 10, 9, 50],
'heatmap-opacity': 0.8
}
});
// 添加城市名称标注图层
map.addLayer({
id: 'cityLabels',
type: 'symbol',
source: 'heatmapSource',
layout: {
'text-field': ['get', 'cityName'], // 从 GeoJSON 的 properties 中获取城市名称
'text-size': 12,
'text-anchor': 'top'
},
paint: {
'text-color': '#000000'
}
});
});前端用到的三方库有:
npm install mapbox-gl h3-js
Mapbox GL JS:
.用于地图渲染和交互
.提供热力图、点图、矢量图层等功能
.需要通过 Mapbox API Token 进行授权
H3:
.用于地理数据的六边形网格化处理
.提供高效的地理数据索引和聚合功能
.在热力图中,H3 索引可以用于生成六边形区域
核心使用组合:生成 H3 索引 → 转换为 GeoJSON → 使用 Mapbox 渲染热力图
服务端数据:
方式1:存储H3索引(以h3索引的方式生成热力图案例-其本质h3只是用来生成GeoJSON 数据而已)
[
{
"h3Index": "81003fffffffffff",//必要固定字段
"value": 10, // 热力图权重 必要固定字段
"cityName": "Beijing" // 自定义字段 城市名称
"category": "A", // 自定义的字段 这里分类信息(可选)
},
{
"h3Index": "81007fffffffffff",
"value": 5,
"cityName": "Beijing" // 自定义字段 城市名称
"category": "B"
}
]
前端转换示例代码:
import { h3SetToFeatureCollection } from 'h3-js';
// 示例服务端返回的 H3 索引数据
const h3Data = [
{ h3Index: "81003fffffffffff", value: 10, cityName: "Beijing" },
{ h3Index: "81007fffffffffff", value: 5, cityName: "Shanghai" }
];
// 转换为 GeoJSON
const geojsonData = h3SetToFeatureCollection(
h3Data.map(item => item.h3Index), // 提取 H3 索引
h3Index => ({
value: h3Data.find(item => item.h3Index === h3Index).value, // 映射权重
cityName: h3Data.find(item => item.h3Index === h3Index).cityName // 保留城市属性
})
);
console.log(geojsonData);
转换后结构应该是:
geojsonData={
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"value": 10, // 热力图权重
"cityName": "Beijing" // 城市名称
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[116.397389, 39.908860],
[116.400000, 39.909000],
[116.395000, 39.907000],
[116.397389, 39.908860]
]
]
}
},
{
"type": "Feature",
"properties": {
"value": 5,
"cityName": "Beijing" // 城市名称
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[116.400000, 39.909000],
[116.403000, 39.910000],
[116.398000, 39.908000],
[116.400000, 39.909000]
]
]
}
}
]
}
方式2:存储GeoJSON数据
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"value": 10, // 热力图权重
"cityName": "Beijing" // 自定义字段 城市名称
"category": "A", // 自定义字段 分类信息(可选)
},
"geometry": {
"type": "Point", // 或 "Polygon"
"coordinates": [116.397389, 39.908860] // 经纬度坐标
}
},
{
"type": "Feature",
"properties": {
"value": 5,
"cityName": "Beijing" // 自定义字段 城市名称
"category": "B"
},
"geometry": {
"type": "Point",
"coordinates": [116.400000, 39.909000]
}
}
]
}服务器存储哪种类型指标参考:
.数据量
如果数据量大,建议存储 H3 索引,前端或中间层动态转换为 GeoJSON
如果数据量小,可以直接存储 GeoJSON
.动态分辨率
如果需要根据地图缩放级别动态调整分辨率,存储 H3 索引更合适
如果分辨率固定,存储 GeoJSON 更简单
.前端复杂度
储 H3 索引需要前端或中间层处理
存储 GeoJSON 前端可以直接使用
结论推荐:
大规模地理数据:存储 H3 索引,前端使用 H3 库动态转换为 GeoJSON
小规模地理数据:直接存储 GeoJSON,前端直接加载渲染
还没有评论哦,来抢个沙发吧!