城脉 CityPulse — AI时空热力可视化平台
参赛作品 | 腾讯位置服务 × CSDN 征文大赛 主题:AI赋能 重塑地图智能新体验 技术栈:HTML5 + CSS3 + JavaScript + 腾讯位置服务 JS API GL + ECharts
一、项目概述
在城市化进程不断加速的今天,城市人流动向的实时感知已成为智慧城市建设的核心命题。传统的静态数据看板只能展示某一时刻的快照,无法揭示城市脉搏的动态演变规律。城脉 CityPulse 由此而生——一款基于腾讯位置服务 JS API GL 的 AI 时空热力可视化平台,将城市级人流、车流、消费热力数据以3D热力图的形式实时渲染,让用户一眼看清城市脉动。
核心能力:
- 🏙️ 8大城市实时切换:北京、上海、广州、深圳、成都、杭州、武汉、西安
- ⏱️ 24帧时空动画:还原城市热力从凌晨到深夜的演变规律
- 📊 ECharts 统计分析:密度折线图 + 雷达图,双视角洞察城市活力
- 🧠 AI 洞察引擎:基于热力数据自动生成城市活力分析报告
- 📤 多格式数据导出:CSV / JSON / GeoJSON

二、设计理念
2.1 为什么选择「热力可视化」?
城市热力图是最直观、最高密度的空间数据表达形式。相比于散点图,热力图通过颜色渐变(深蓝→橙→红)将密度信息压缩到一个视觉通道,让用户无需阅读任何数字就能感知「哪里热闹、哪里冷清」。而加入时间维度后,热力图从静态快照升级为时空纪录片,这才是真正有价值的城市数据叙事。

2.2 视觉语言:深色科技风(Dark Science Fiction)
设计参考深色科技风格,以深蓝黑为底,辅以科技蓝(#00d4ff)和紫罗兰(#7c3aed)作为点缀。高对比度确保数据在高密度热力叠加时依然清晰可辨。整体视觉调性与腾讯位置服务本身的科技感高度吻合。
| 元素 | 色值 | 用途 |
|---|---|---|
| 科技蓝 | #00d4ff | 主强调色,热力峰值 |
| 紫罗兰 | #7c3aed | 次级强调 |
| 警示橙 | #f97316 | 中等密度热力 |
| 深蓝 | #1e3a8a | 低密度热力 |
| 背景 | #0a0e1a | 全局背景 |
| 面板 | #111827 | 侧边栏/卡片背景 |
2.3 从「看数据」到「读懂城市」
平台不只是展示数据,更通过以下设计帮助用户解读数据:
- 热点排行榜:实时排序 Top 10 热点区域,一眼看出生理点和冷区
- 统计概览卡片:POI 总数、峰值区域、平均密度、热点数量四个关键指标秒级刷新
- 时间轴:24帧时间轴 + 播放控制,拖动进度条可精确定位到某一时刻
三、技术架构
3.1 整体架构
┌─────────────────────────────────────────────────┐
│ HTML5 页面结构 │
├──────────┬─────────────────────────┬────────────┤
│ 控制面板 │ 腾讯地图容器 (GL) │ 信息面板 │
│ (左侧) │ #tencentMap (3D热力图) │ (右侧) │
├──────────┴─────────────────────────┴────────────┤
│ CSS3 样式层 (深色科技风) │
├─────────────────────────────────────────────────┤
│ app.js (主逻辑) │ qqmap-adapter.js (地图适配) │
│ ┌─────────────┐ │ ┌─────────────────────────────┐│
│ │ 数据生成器 │ │ │ 腾讯地图 JS API GL 封装 ││
│ │ 事件绑定 │ │ │ init / addHeatmap / addMarkers││
│ │ ECharts │ │ │ switchCity / toggle3D / reset ││
│ │ AI洞察 │ │ └─────────────────────────────┘│
│ └─────────────┘ │
└─────────────────────────────────────────────────┘
3.2 模块设计
地图适配层:qqmap-adapter.js
适配器模式将腾讯地图 API 封装为统一的内部接口,屏蔽底层差异:
// 初始化地图并设置城市中心
adapter.init('tencentMap').then(() => {
adapter.addHeatmap(heatData, { radius: 80, intensity: 0.5 });
adapter.addMarkers(hotspots.map(h => ({ lat: h.lat, lng: h.lng, name: h.name })));
});
// 切换城市
adapter.switchCity('上海');
// 切换 3D/2D 视图
adapter.toggle3D(); // 返回新的 is3D 状态
// 重置视角
adapter.resetView();
// 设置俯角
adapter.setPitch(45);
数据生成层:app.js → lMD()
城市数据(8城 × 24帧 × ~120点/帧)通过数学模型实时生成,模拟真实城市热力分布规律:
function lMD() {
var cl = ["北京", "上海", "广州", ...];
var cm = { "北京": [39.9042, 116.4074], ... };
var hm = { "北京": ["国贸CBD", "中关村", ...], ... };
cl.forEach(function(city) {
var cx = cm[city];
var frames = [];
// 每城市生成 24 帧(每帧代表一天中的一小时)
for (var f = 0; f < 24; f++) {
var points = [];
var count = 80 + Math.floor(Math.random() * 40);
for (var i = 0; i < count; i++) {
// 在城市中心点 0.15° 范围内随机撒点
var lat = cx[0] + (Math.random() - 0.5) * 0.15;
var lng = cx[1] + (Math.random() - 0.5) * 0.15;
// 模拟正弦波动的热力权重(高峰时段权重更高)
var hourFactor = Math.sin((f / 24) * Math.PI * 2 - Math.PI / 2) * 0.5 + 0.5;
var weight = 0.3 + Math.random() * 0.7 * hourFactor;
points.push({ lat, lng, weight });
}
frames.push(points);
}
// 生成热点标记(围绕城市中心环形分布)
var hotspots = hm[city].map((name, i) => {
var angle = (i / hm[city].length) * Math.PI * 2;
var dist = 0.02 + Math.random() * 0.05;
return {
name,
lat: cx[0] + Math.sin(angle) * dist,
lng: cx[1] + Math.cos(angle) * dist,
value: Math.floor(600 + Math.random() * 800),
category: ['商业', '交通', '居住', '娱乐', '办公'][i % 5]
};
});
S.cD[city] = { center: { lat: cx[0], lng: cx[1] }, frames, hotspots };
});
}
动画引擎:app.js → pAnim()
function pAnim() {
if (!S.play) return;
S.cf = (S.cf + 1) % 24; // 循环播放 24 帧
var cityData = S.cD[S.cC];
if (cityData) {
S.hD = cityData.frames[S.cf] || [];
rHM(); // 刷新热力图层
upTLUI(); // 更新时间轴 UI
}
var interval = Math.round(500 / S.spd); // 支持 1x~10x 变速
S.pt = setTimeout(pAnim, interval);
}
四、核心功能演示
4.1 时空动画播放
点击「播放时空动画」按钮,系统自动以可配置的速率(1x~10x)循环播放24帧热力演变。进度条实时反映当前帧位置,点击进度条任意位置可跳转。
4.2 AI 洞察分析
点击顶部「🧠 AI洞察分析」按钮,平台在1.5秒内分析当前城市、当前帧的全部热力数据,生成包含以下内容的结构化报告:
- 核心发现:识别最热区域(峰值热点)、热力走廊分布形态、次级热点增长率
- 时段特征:结合当前帧对应时段(凌晨/早高峰/午间/晚高峰等)解读人流规律
- 区域活力评分:综合人口密度、出行轨迹、时段特征给出 60-90 分的量化评分
- 出行建议:基于热力趋势预测未来2小时状态,提供错峰出行建议
4.3 数据导出
支持 CSV(带 BOM 的 UTF-8 编码,Excel 完美兼容)、JSON、GeoJSON 三种格式。导出范围可选当前帧或全部24帧时间轴数据,可直接用于后续数据分析或二次可视化。
4.4 3D 视角与视觉调参
- 3D/2D 切换:一键切换立体视角,增强空间纵深感
- 俯视角控制:0°~60° 俯角滑块控制,观察热力垂直分布
- 热力强度 / 半径 / 高度倍数:三个视觉参数实时调整,即时反映在地图上
五、关键代码解读
5.1 腾讯地图 GL 热力图层封装
class QQMapAdapter {
constructor() {
this.map = null;
this.heatmapOverlay = null;
this.markers = [];
this.is3D = false;
}
async init(containerId) {
return new Promise((resolve) => {
this.map = new TMap.Map(containerId, {
center: new TMap.LatLng(39.9042, 116.4074),
zoom: 12,
pitch: 45,
mapStyleId: 'style_night', // 深色地图底图
});
this.map.on('init', () => resolve());
});
}
addHeatmap(points, opts = {}) {
const radius = opts.radius || 80;
const intensity = opts.intensity || 0.5;
const data = points.map(p => ({
...new TMap.LatLng(p.lat, p.lng),
weight: p.weight || 1
}));
if (this.heatmapOverlay) {
this.map.removeLayer(this.heatmapOverlay);
}
this.heatmapOverlay = new TMap.visualization.Heatmap({
radius: radius,
intensity: intensity,
opacity: opts.opacity || 0.85,
gradient: { // 自定义蓝→橙→红渐变
0.0: '#1e3a8a',
0.4: '#f97316',
0.8: '#ef4444',
1.0: '#dc2626'
}
});
this.map.addLayer(this.heatmapOverlay);
this.heatmapOverlay.setData(data);
}
addMarkers(hotspots) {
this.markers.forEach(m => this.map.remove(m));
this.markers = hotspots.map(h => {
const marker = new TMap.MultiMarker({
id: 'hotspot-markers',
map: this.map,
styles: {
marker: new TMap.MarkerStyle({
width: 24,
height: 35,
anchor: { x: 12, y: 35 },
color: '#00d4ff',
size: 16
})
},
geometries: [{
id: h.name,
styleId: 'marker',
position: new TMap.LatLng(h.lat, h.lng)
}]
});
return marker;
});
}
switchCity(city) {
const centers = {
"北京": [39.9042, 116.4074],
"上海": [31.2304, 121.4737],
// ...
};
const [lat, lng] = centers[city];
this.map.setCenter(new TMap.LatLng(lat, lng));
}
toggle3D() {
this.is3D = !this.is3D;
this.map.setPitch(this.is3D ? 45 : 0);
return this.is3D;
}
resetView() {
this.map.resetViewport();
}
setPitch(degrees) {
this.map.setPitch(degrees);
}
flashMarker(name, lat, lng) {
// 高亮闪烁指定标记
}
}
5.2 ECharts 密度折线图
S.chs.d = echarts.init(D.densityChart);
S.chs.d.setOption({
backgroundColor: 'transparent',
grid: { top: 30, right: 15, bottom: 25, left: 40 },
xAxis: {
type: 'category',
data: ['06', '08', '10', '12', '14', '16', '18', '20', '22'],
axisLine: { lineStyle: { color: '#334155' } },
axisLabel: { color: '#64748b', fontSize: 10 }
},
yAxis: {
type: 'value',
splitLine: { lineStyle: { color: '#1e293b' } },
axisLabel: { color: '#64748b', fontSize: 10 }
},
series: [{
type: 'line',
smooth: true,
data: [320, 450, 680, 920, 780, 1050, 1200, 880, 520],
areaStyle: {
color: {
type: 'linear', x: 0, y: 0, x2: 0, y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(0,212,255,0.4)' },
{ offset: 1, color: 'rgba(0,212,255,0.05)' }
]
}
},
lineStyle: { color: '#00d4ff', width: 2 },
itemStyle: { color: '#00d4ff' },
symbol: 'circle', symbolSize: 4
}],
tooltip: {
trigger: 'axis',
backgroundColor: '#1e293b',
borderColor: '#334155',
textStyle: { color: '#f1f5f9', fontSize: 12 }
}
});
六、作品亮点
6.1 为什么这个作品有竞争力?
① 时空维度是差异点。大多数参赛作品展示的是静态热力,而 CityPulse 通过24帧动画揭示城市热力的一天变化规律——这是腾讯位置服务热力图层能力的完整展现。
② 技术栈纯净,依赖腾讯官方。完全基于腾讯位置服务 JS API GL + ECharts 构建,未引入第三方可视化库(与活动「使用腾讯位置服务」的主题高度契合)。
③ 从数据到叙事。AI 洞察模块将纯数字热力数据转化为自然语言描述,让非技术用户也能「读懂」城市。
④ 全功能闭环。数据生成 → 可视化 → 分析 → 导出,形成了完整的数据消费链路。
6.2 技术局限与未来方向
- 当前数据为数学模型模拟,尚未接入腾讯位置服务的真实热力数据 API(个人认证不支持)
- 3D 高度倍数目前仅调整热力半径,未来可结合
Extrude实现真正的3D柱状热力 - AI 洞察为规则引擎,可升级为接入大模型 API 的真正 AI 分析
七、结语
城脉 CityPulse 将腾讯位置服务 GL 版的 3D 地图能力、热力图层与时空动画结合,探索了一种「用眼睛看城市脉搏」的交互范式。希望通过这个作品,让更多人感受到城市数据的生命力和空间智能的魅力。