关于 mapbox-data-visualization-patterns
为使用 Mapbox 地图进行数据可视化的开发者提供模式指南,涵盖专题图、热力图、3D 表达和动态样式,并包含大型数据集的性能建议。
主要功能
- 01专题分级设色地图
- 02热力图与点聚类
- 033D 挤出与数据驱动样式
- 04时间序列动画
- 05大型数据集性能优化
- 06提供图例及可视化参考
适用场景
- 01按区域比较人口或销售数据
- 02展示事件位置密度
- 03按属性设置地图要素样式
- 04呈现随时间变化的数据
- 05优化大型地图数据的加载与显示
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mapbox/ mapbox-agent-skills --skill mapbox-data-visualization-patterns安装后在 Claude Code 中输入/mapbox-data-visualization-patterns确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
AGENTS.mdevals/evals.jsonreferences/3d-extrusions.mdanimation.mdcircles-lines.mdclustering.mdlegends-use-cases.mdperformance.md详细介绍
数据可视化模式技能
全面介绍在 Mapbox 地图上可视化数据的模式,涵盖分级统计图、热力图、3D 拉伸、数据驱动样式、动态可视化,以及面向数据密集型应用的性能优化。
何时使用此技能
在以下情况下使用此技能:
- 在地图上可视化统计数据(人口、销售额、人口统计数据)
- 创建以颜色标示区域的分级统计图
- 构建热力图或聚类图以可视化密度
- 添加 3D 可视化(建筑高度、地形高程)
- 根据属性实现数据驱动样式
- 为时间序列数据添加动画
- 处理需要优化的大型数据集
可视化类型
分级统计图
最适合: 区域数据(州、县、邮政编码区域)、统计对比
模式: 根据数据值为多边形着色
map.on('load', () => {
// Add data source (GeoJSON with properties)
map.addSource('states', {
type: 'geojson',
data: 'https://example.com/states.geojson' // Features with population property
});
// Add fill layer with data-driven color
map.addLayer({
id: 'states-layer',
type: 'fill',
source: 'states',
paint: {
'fill-color': [
'interpolate',
['linear'],
['get', 'population'],
0,
'#f0f9ff', // Light blue for low population
500000,
'#7fcdff',
1000000,
'#0080ff',
5000000,
'#0040bf', // Dark blue for high population
10000000,
'#001f5c'
],
'fill-opacity': 0.75
}
});
// Add border layer
map.addLayer({
id: 'states-border',
type: 'line',
source: 'states',
paint: {
'line-color': '#ffffff',
'line-width': 1
}
});
// Add hover effect with reusable popup
const popup = new mapboxgl.Popup({
closeButton: false,
closeOnClick: false
});
map.on('mousemove', 'states-layer', (e) => {
if (e.features.length > 0) {
map.getCanvas().style.cursor = 'pointer';
const feature = e.features[0];
popup
.setLngLat(e.lngLat)
.setHTML(
`
<h3>${feature.properties.name}</h3>
<p>Population: ${feature.properties.population.toLocaleString()}</p>
`
)
.addTo(map);
}
});
map.on('mouseleave', 'states-layer', () => {
map.getCanvas().style.cursor = '';
popup.remove();
});
});
step与interpolate: 上面的示例使用interpolate创建平滑的颜色渐变。对于离散的颜色分档(例如“低/中/高”),改用['step', ['get', 'population'], '#f0f0f0', 500000, '#fee0d2', 2000000, '#fc9272', 10000000, '#de2d26']。当数据具有自然分类,或需要关注精确的边界值时,优先使用step。
颜色比例尺策略:
// Linear interpolation (continuous scale)
'fill-color': [
'interpolate',
['linear'],
['get', 'value'],
0, '#ffffcc',
25, '#78c679',
50, '#31a354',
100, '#006837'
]
// Step intervals (discrete buckets)
'fill-color': [
'step',
['get', 'value'],
'#ffffcc', // Default color
25, '#c7e9b4',
50, '#7fcdbb',
75, '#41b6c4',
100, '#2c7fb8'
]
// Case-based (categorical data)
'fill-color': [
'match',
['get', 'category'],
'residential', '#ffd700',
'commercial', '#ff6b6b',
'industrial', '#4ecdc4',
'park', '#45b7d1',
'#cccccc' // Default
]
热力图
最适合: 点密度、事件位置、事故聚类
模式: 可视化点的密度
map.on('load', () => {
// Add data source (points)
map.addSource('incidents', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [-122.4194, 37.7749]
},
properties: {
intensity: 1
}
}
// ... more points
]
}
});
// Add heatmap layer
map.addLayer({
id: 'incidents-heat',
type: 'heatmap',
source: 'incidents',
maxzoom: 15,
paint: {
// Increase weight based on intensity property
'heatmap-weight': ['interpolate', ['linear'], ['get', 'intensity'], 0, 0, 6, 1],
// Increase intensity as zoom level increases
'heatmap-intensity': ['interpolate', ['linear'], ['zoom'], 0, 1, 15, 3],
// Color ramp for heatmap
'heatmap-color': [
'interpolate',
['linear'],
['heatmap-density'],
0,
'rgba(33,102,172,0)',
0.2,
'rgb(103,169,207)',
0.4,
'rgb(209,229,240)',
0.6,
'rgb(253,219,199)',
0.8,
'rgb(239,138,98)',
1,
'rgb(178,24,43)'
],
// Adjust radius by zoom level
'heatmap-radius': ['interpolate', ['linear'], ['zoom'], 0, 2, 15, 20],
// Decrease opacity at higher zoom levels
'heatmap-opacity': ['interpolate', ['linear'], ['zoom'], 7, 1, 15, 0]
}
});
// Add circle layer for individual points at high zoom
map.addLayer({
id: 'incidents-point',
type: 'circle',
source: 'incidents',
minzoom: 14,
paint: {
'circle-radius': ['interpolate', ['linear'], ['zoom'], 14, 4, 22, 30],
'circle-color': '#ff4444',
'circle-opacity': 0.8,
'circle-stroke-color': '#fff',
'circle-stroke-width': 1
}
});
});
最佳实践
颜色无障碍
// Use ColorBrewer scales for accessibility
// https://colorbrewer2.org/
// Good: Sequential (single hue)
const sequentialScale = ['#f0f9ff', '#bae4ff', '#7fcdff', '#0080ff', '#001f5c'];
// Good: Diverging (two hues)
const divergingScale = ['#d73027', '#fc8d59', '#fee08b', '#d9ef8b', '#91cf60', '#1a9850'];
// Good: Qualitative (distinct categories)
const qualitativeScale = ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00'];
// Avoid: Red-green for color-blind accessibility
// Use: Blue-orange or purple-green instead
错误处理
// Handle missing or invalid data
map.on('load', () => {
map.addSource('data', {
type: 'geojson',
data: dataUrl
});
map.addLayer({
id: 'data-viz',
type: 'fill',
source: 'data',
paint: {
'fill-color': [
'case',
['has', 'value'], // Check if property exists
['interpolate', ['linear'], ['get', 'value'], 0, '#f0f0f0', 100, '#0080ff'],
'#cccccc' // Default color for missing data
]
}
});
// Handle map errors
map.on('error', (e) => {
console.error('Map error:', e.error);
});
});
数据大小规则
- < 1 MB:直接使用 GeoJSON
- 1–10 MB:根据复杂程度考虑使用 GeoJSON 或矢量瓦片
- > 10 MB:使用矢量瓦片(将数据上传到 Mapbox,作为瓦片集)
实现详情请参阅 references/performance.md。
参考文件
如需更多可视化模式,请加载相关参考文件:
- references/clustering.md — 点聚类、自定义聚类属性、聚类与热力图的比较
- references/3d-extrusions.md — 3D 建筑拉伸、自定义数据源、数据驱动高度
- references/circles-lines.md — 圆形/气泡地图、线数据可视化、交通流样式
- references/animation.md — 时间序列动画、实时数据更新、平滑过渡
- references/performance.md — 矢量瓦片与 GeoJSON、要素状态、筛选、渐进式加载
- references/legends-use-cases.md — 图例 UI、数据检查器、数据预处理、选举/COVID/房地产示例
资源
- Mapbox Expression Reference
- ColorBrewer - 地图配色方案
- Turf.js - 空间分析
- Simple Statistics - 数据分类
- Data Visualization Tutorials
评论
支持 Markdown