零基础可视化看板搭建:从交互到下钻全流程
一、前言:从数据展示到交互洞察的跃迁
在前两个实验中,我们分别完成了浏览器市场分析大屏的静态布局与数据接入,以及用户画像大屏的多维度数据绑定和筛选器联动。然而,一个真正具备商业价值的可视化大屏,不仅需要"能看",更需要"能交互"——让用户通过简单的点击、切换,就能深入挖掘数据背后的洞察。
本实验将带领大家进入Max蓝图编辑器的高级交互领域,实现三大核心功能:
Tab导航切换:通过图层可见性控制,在同一文件中实现"市场分析"与"用户画像"两个大屏的无缝切换
地图省份点击下钻:点击地图省份,右侧核心指标卡动态更新为该省份数据
热力图动态渲染:根据用户数自动渲染地图颜色深浅,实现地理分布的可视化
无需编写后端API,无需复杂的前端事件监听,只需在蓝图编辑器中拖拽节点、配置逻辑,即可完成企业级交互大屏。
二、实验目标与核心技能图谱
2.1 实验目的
| 能力维度 | 具体技能 |
|---|---|
| 图层管理 | 使用图层可见性控制实现大屏内容切换 |
| 导航交互 | 使用Tab列表组件配置页面内容显示/隐藏 |
| 地理下钻 | 使用地图组件交互事件实现省份点击联动 |
| 数据联动 | 配置指标卡组件根据地图点击动态更新数据 |
| 热力渲染 | 基于adcode映射实现地图热力层动态着色 |
2.2 实验环境
数据来源:团队私有数据库(MySQL)
前置实验:实验6-1(静态布局)、实验6-2(数据接入)
2.3 最终效果预览
完成本实验后,您的大屏将具备以下交互能力:
✅ 顶部Tab导航一键切换"市场分析"与"用户画像"
✅ 地图根据当前浏览器用户数自动渲染颜色深浅(热力图)
✅ 点击任意省份,右侧四个核心指标卡实时刷新为该省份数据
✅ 切换浏览器筛选器,地图热力图同步更新
三、整体交互架构设计
3.1 系统交互全景图
3.2 两大核心交互链路
链路一:大屏切换交互(图层可见性控制)
Tab列表组件 │ ├── 点击"市场分析" (id=1) ──→ 分支判断(id==1)为真 │ ├── 设置图层:市场分析组 → 显示 │ └── 设置图层:用户画像组 → 隐藏 │ └── 点击"用户画像" (id=2) ──→ 分支判断(id==1)为假 ├── 设置图层:市场分析组 → 隐藏 └── 设置图层:用户画像组 → 显示链路二:地图省份点击联动(地理下钻)
基础平面地图(区域热力层) │ ├── 点击区域时事件 ──→ 提取地区名称(并行数据处理) │ │ │ ├── 省份全称 → 简称映射 │ └── 存入全局变量 window.globalProvinceName │ │ │ └──→ 省份核心指标查询(SQL请求) │ │ │ ├── 读取 window.globalProvinceName │ ├── 读取 window.GLOBAL_SELECTED_BROWSER │ └── 执行动态SQL │ │ │ └──→ 省份核心指标分发(并行数据处理) │ │ │ ├── 分支1:总用户数 → 指标卡1 │ ├── 分支2:平均年龄 → 指标卡2 │ ├── 分支3:本科占比 → 指标卡3 │ └── 分支4:中高收入占比 → 指标卡4 │ └── 热力渲染链路(独立) │ ├── 地理边界geojson加载完成 ──→ 提取adcode映射表 │ │ │ └── 存入 window.globalProvinceAdcode │ │ └── 浏览器切换/页面加载 ──→ 各省份用户数查询(SQL) │ └──→ 地图数据与用户数映射 │ └──→ 导入热力值数据接口四、核心技术深度解析
4.1 图层可见性控制:单文件多屏方案
设计背景:在实际业务场景中,一个数据分析项目往往包含多个视角(如市场分析、用户画像、运营监控)。如果每个视角都创建独立的大屏文件,会导致:
维护成本高(样式、数据源需重复配置)
切换体验差(页面跳转有白屏)
状态丢失(筛选器状态无法跨页面传递)
Max解决方案:通过图层组+可见性控制,在同一文件中管理多个大屏内容。
技术原理:
将"市场分析"所有组件放入一个图层组(如"市场分析组")
将"用户画像"所有组件放入另一个图层组(如"用户画像组")
通过Tab列表组件的点击事件,控制两个组的
显示/隐藏状态
优势对比:
| 方案 | 文件数 | 切换体验 | 状态共享 | 维护成本 |
|---|---|---|---|---|
| 独立文件 | 2+ | 差(页面跳转) | 不支持 | 高 |
| 图层切换(本方案) | 1 | 优(无刷新) | 支持 | 低 |
4.2 地图交互事件体系
Max地图组件(基础平面地图)提供了丰富的交互事件:
| 事件名称 | 触发时机 | 输出数据 |
|---|---|---|
当数据接口地理边界geojson数据加载完成时 | 地图GeoJSON加载完成 | GeoJSON对象(含features数组) |
点击区域时 | 用户点击某个省份区域 | { name, adcode, ... } |
鼠标移入区域触发 | 鼠标悬停省份 | { name, adcode, ... } |
鼠标移出区域触发 | 鼠标离开省份 | { name, adcode, ... } |
本实验使用的事件:
点击区域时:触发省份下钻,更新指标卡当数据接口地理边界geojson数据加载完成时:提取adcode映射表,为热力渲染做准备
4.3 省份名称标准化:全称与简称的映射
问题背景:地图组件返回的省份名称是全称(如"江苏省"、"广西壮族自治区"),但数据库中存储的是简称(如"江苏"、"广西")。直接用于SQL查询会导致匹配失败。
解决方案:建立双向映射表,在数据流中进行名称转换。
// 特殊映射表(直辖市、自治区、特别行政区) const specialMap = { '北京市': '北京', '天津市': '天津', '上海市': '上海', '重庆市': '重庆', '广西壮族自治区': '广西', '内蒙古自治区': '内蒙古', '西藏自治区': '西藏', '宁夏回族自治区': '宁夏', '新疆维吾尔自治区': '新疆', '香港特别行政区': '香港', '澳门特别行政区': '澳门' };通用处理规则:
优先匹配特殊映射表(处理直辖市、自治区等特殊情况)
通用处理:去除末尾的"省"、"自治区"、"市"后缀
最终得到数据库可识别的简称
4.4 行政区划代码(adcode)映射
什么是adcode?adcode是国家统计局发布的行政区划代码,是地图渲染的"身份证"。Max地图组件通过adcode识别每个省份的边界和位置。
为什么需要adcode映射?
地图热力层的数据格式要求:
{ "name": "江苏", "value": 1500, "area_id": 320000 }其中area_id就是adcode。因此,我们需要建立"省份名称 → adcode"的映射关系。
数据来源:地图组件内置的GeoJSON数据中已经包含了每个省份的adcode,只需在加载完成后提取即可。
五、实验步骤详解
5.1 Step 1:配置大屏Tab导航切换
5.1.1 设计思路
Tab列表组件是一个可自定义选项的交互组件。本实验的核心技巧是"透明化"——将Tab列表的背景色、选中背景色、悬浮背景色的透明度都设为0,使其与顶部的导航按钮完全重合,给用户"点击按钮切换页面"的错觉,实际上是通过图层可见性控制实现内容切换。
5.1.2 组件配置
(1)添加Tab列表组件
从组件库拖拽"Tab列表"组件到画布顶部导航区域
调整大小和位置,使其与两个导航按钮("市场分析"、"用户画像")完全重合
(2)样式配置(透明化处理)
在Tab列表组件的基本设置中:
行数:1
列数:2
在标签默认配置中,将以下三项的透明度设置为0:
背景颜色
选中背景色
悬浮背景色
效果:Tab列表组件完全透明,用户只能看到底层的导航按钮文字,但点击区域实际由Tab列表捕获。
(3)数据配置
在数据面板中,保留2列数据:
[ { "id": 1, "content": "" }, { "id": 2, "content": "" } ]id:用于分支判断,区分"市场分析"和"用户画像"content:设为空字符串(因为按钮文字由底层样式提供)
配置完成后,点击刷新数据按钮。
5.1.3 蓝图编辑器配置
(1)导出组件
将以下组件导出到蓝图编辑器:
"市场分析"组(图层组)
"用户画像"组(图层组)
Tab列表组件
(2)添加分支判断节点
添加"分支判断"节点,配置处理方法:
return data.id == 1;逻辑说明:
当用户点击"市场分析"时,Tab列表输出
{ id: 1 },表达式为true当用户点击"用户画像"时,Tab列表输出
{ id: 2 },表达式为false
(3)配置"满足"分支(id=1,显示市场分析)
在"分支判断"的满足分支上,添加两个"设置图层可见性"动作:
| 目标图层 | 动作 |
|---|---|
| 市场分析组 | 显示 |
| 用户画像组 | 隐藏 |
(4)配置"不满足"分支(id=2,显示用户画像)
在"分支判断"的不满足分支上,添加两个"设置图层可见性"动作:
| 目标图层 | 动作 |
|---|---|
| 市场分析组 | 隐藏 |
| 用户画像组 | 显示 |
(5)节点连线
5.1.4 验证要点
[ ] 点击"市场分析"按钮,市场分析大屏显示,用户画像大屏隐藏
[ ] 点击"用户画像"按钮,用户画像大屏显示,市场分析大屏隐藏
[ ] 切换过程无页面刷新,体验流畅
5.2 Step 2:配置地图省份点击联动
5.2.1 设计思路
用户点击地图省份 → 提取省份名称 → 查询该省份核心指标 → 分发到四个指标卡。这是典型的地理下钻分析(Geo-drilldown)。
5.2.2 核心组件配置
(1)提取地区名称(并行数据处理节点)
作用:接收地图点击事件输出的数据对象,提取省份名称,通过映射表转换为简称,存入全局变量。
节点配置:
添加"并行数据处理"节点,重命名为"提取地区名称"。
处理方法代码:
// 省份特殊映射(直辖市、自治区、特别行政区) const specialMap = { '北京市': '北京', '天津市': '天津', '上海市': '上海', '重庆市': '重庆', '广西壮族自治区': '广西', '内蒙古自治区': '内蒙古', '西藏自治区': '西藏', '宁夏回族自治区': '宁夏', '新疆维吾尔自治区': '新疆', '香港特别行政区': '香港', '澳门特别行政区': '澳门' }; let provinceName = data.name; // 优先使用特殊映射 if (specialMap[provinceName]) { provinceName = specialMap[provinceName]; } else { // 通用处理:去除末尾的"省"、"自治区"、"市" provinceName = provinceName.replace(/(省|自治区|市)$/, ''); } // 存入全局变量,供后续SQL节点读取 window.globalProvinceName = provinceName; return provinceName;代码解析:
| 处理阶段 | 逻辑 | 示例 |
|---|---|---|
| 特殊映射 | 直接查表 | "北京市" → "北京" |
| 通用处理 | 正则去除后缀 | "江苏省" → "江苏" |
| 全局存储 | window.globalProvinceName | 跨节点共享 |
(2)省份核心指标查询(SQL请求节点)
作用:根据当前选中的浏览器和点击的省份,查询四个核心指标。
节点配置:
添加"SQL请求"节点,重命名为"省份核心指标查询"。
处理方法代码:
const selectedProvince = window.globalProvinceName; console.log("点击的省份名称(处理后):", selectedProvince); const selectedBrowser = window.GLOBAL_SELECTED_BROWSER; const sql = ` -- 指标1:总用户数 select 'total_users' as name, sum(user_count) as value from labs.user_profile_stats where browser_name = '${selectedBrowser}' and province = '${selectedProvince}' union all -- 指标2:平均年龄(加权平均) select 'avg_age' as name, round(sum(age * user_count) / sum(user_count), 0) as value from labs.user_profile_stats where browser_name = '${selectedBrowser}' and province = '${selectedProvince}' union all -- 指标3:本科及以上占比 select 'high_edu_ratio' as name, round( sum(case when edu in ('本科', '硕士及以上') then user_count else 0 end) * 100.0 / sum(user_count), 2 ) as value from labs.user_profile_stats where browser_name = '${selectedBrowser}' and province = '${selectedProvince}' union all -- 指标4:中高收入占比 select 'high_income_ratio' as name, round( sum(case when income in ('5001~8000元', '8001~12000元', '12000元以上') then user_count else 0 end) * 100.0 / sum(user_count), 2 ) as value from labs.user_profile_stats where browser_name = '${selectedBrowser}' and province = '${selectedProvince}' `; console.log("生成的省份核心指标SQL:", sql); return sql;SQL设计要点:
| 指标 | 计算逻辑 | 精度 |
|---|---|---|
| 总用户数 | SUM(user_count) | 整数 |
| 平均年龄 | SUM(age * user_count) / SUM(user_count) | 0位小数 |
| 本科及以上占比 | CASE WHEN条件计数 / 总数 × 100% | 2位小数 |
| 中高收入占比 | 多值匹配 + 条件计数 / 总数 × 100% | 2位小数 |
为什么用
UNION ALL?四个指标结构相同(name, value),合并为一次查询减少数据库往返。每个指标通过name字段标识,便于后续分发。
(3)省份核心指标分发(并行数据处理节点)
作用:将SQL返回的四行数据拆分为四个独立数值,分别发送给对应的指标卡。
节点配置:
添加"并行数据处理"节点,重命名为"省份核心指标分发"。
分支1:总用户数 → 总用户数指标卡
var item = data.find(item => item.name === 'total_users'); return [{ value: item ? item.value : 0 }];分支2:平均年龄 → 平均年龄指标卡
var item = data.find(item => item.name === 'avg_age'); return [{ value: item ? item.value : 0 }];分支3:本科及以上占比 → 本科及以上占比指标卡
var item = data.find(item => item.name === 'high_edu_ratio'); return [{ value: item ? item.value : 0 }];分支4:中高收入占比 → 中高收入占比指标卡
var item = data.find(item => item.name === 'high_income_ratio'); return [{ value: item ? item.value : 0 }];5.2.3 蓝图连线
5.2.4 验证要点
[ ] 点击地图上的江苏省,指标卡显示江苏省的数据
[ ] 点击地图上的广东省,指标卡显示广东省的数据
[ ] 指标数据与当前选中的浏览器一致(如当前选中Chrome,则显示Chrome在江苏的数据)
[ ] 切换浏览器后,再次点击同一省份,数据应相应变化
5.3 Step 3:配置地图热力层动态渲染
5.3.1 设计思路
为了直观展示全国各省份的用户分布,需要在地图上用颜色深浅表示用户数(用户数越多,颜色越深)。这需要完成三个步骤:
提取adcode映射表:从地图GeoJSON中提取"省份名称 → adcode"映射
查询各省份用户数:按浏览器统计每个省份的用户总数
数据映射与格式化:将查询结果匹配adcode,输出热力层所需格式
5.3.2 核心组件配置
(1)提取adcode映射表(并行数据处理节点)
作用:在地图GeoJSON加载完成后,提取每个省份的adcode和名称,建立映射表。
触发时机:区域热力层的当数据接口地理边界geojson数据加载完成时事件
节点配置:
添加"并行数据处理"节点,重命名为"提取adcode映射表"。
处理方法代码:
/** * 提取地理数据中的 adcode 和 name,建立名称→adcode 映射 * @param {Object} data - 地理数据对象(包含 features 数组) * @returns {Object} 名称到 adcode 的映射表 */ function extractAdcodeAndName(data) { if (!data || !Array.isArray(data.features)) { console.error('无效的地图数据格式'); return {}; } const nameToAdcode = {}; data.features.forEach(feature => { const props = feature.properties; if (props && props.adcode && props.name) { nameToAdcode[props.name] = props.adcode; } }); return nameToAdcode; } const mapping = extractAdcodeAndName(data); // 存入全局变量,供后续热力数据映射使用 window.globalProvinceAdcode = mapping; console.log("省份adcode映射表已加载", Object.keys(mapping).length); return mapping;代码解析:
| 步骤 | 操作 | 说明 |
|---|---|---|
| 数据校验 | 检查data.features是否为数组 | 防御性编程 |
| 遍历features | forEach遍历每个省份 | GeoJSON标准结构 |
| 提取属性 | feature.properties.adcode/.name | GeoJSON规范 |
| 全局存储 | window.globalProvinceAdcode | 跨节点共享 |
(2)各省份用户数查询(SQL请求节点)
作用:根据当前选中的浏览器,统计每个省份的用户总数。
节点配置:
添加"SQL请求"节点,重命名为"各省份用户数查询"。
处理方法代码:
const selectedBrowser = window.GLOBAL_SELECTED_BROWSER; const sql = ` SELECT province AS name, SUM(user_count) AS value FROM labs.user_profile_stats WHERE browser_name = '${selectedBrowser}' AND province IS NOT NULL AND province != '' GROUP BY province ORDER BY value DESC `; console.log("生成的所有省份用户数SQL:", sql); return sql;SQL设计要点:
GROUP BY province:按省份聚合ORDER BY value DESC:按用户数降序排列,便于查看TOP省份AND province IS NOT NULL AND province != '':过滤空值,避免地图渲染异常
(3)地图数据与用户数映射(并行数据处理节点)
作用:将SQL查询结果中的省份名称与adcode映射表匹配,生成热力层所需的{ name, value, area_id }格式。
节点配置:
添加"并行数据处理"节点,重命名为"地图数据与用户数映射"。
处理方法代码:
function convertToMapData(data) { if (!Array.isArray(data) || data.length === 0) { return []; } return data.map(item => { const provinceName = item.name; // 第一步:直接匹配 let area_id = window.globalProvinceAdcode[provinceName]; // 第二步:如果直接匹配失败,尝试简化名称 if (!area_id) { const simplifiedName = provinceName.replace( /省|市|自治区|特别行政区|回族|壮族|维吾尔|藏族|苗族/g, '' ); for (const fullName in window.globalProvinceAdcode) { if (fullName.includes(simplifiedName)) { area_id = window.globalProvinceAdcode[fullName]; break; } } } // 第三步:兜底处理 if (!area_id) { // console.warn(`未找到省份 "${provinceName}" 的匹配 adcode`); area_id = "000000"; } return { name: provinceName, value: parseFloat(item.value) || 0, area_id: Number(area_id) }; }); } const result = convertToMapData(data); // console.log("最终返回的地图热力数据:", result); return result;映射策略详解:
| 匹配层级 | 策略 | 适用场景 |
|---|---|---|
| 第一层:直接匹配 | globalProvinceAdcode[provinceName] | 名称完全一致 |
| 第二层:简化匹配 | 去除后缀后模糊匹配 | 数据库简称 vs GeoJSON全称 |
| 第三层:兜底处理 | 使用默认adcode "000000" | 防止渲染崩溃 |
数据格式说明:
热力层要求的数据格式:
[ { "name": "江苏", "value": 1500, "area_id": 320000 }, { "name": "广东", "value": 2300, "area_id": 440000 } ]name:省份名称(用于tooltip显示)value:用户数(用于颜色深浅计算)area_id:adcode(用于定位省份边界)
5.3.3 蓝图连线(热力渲染链路)![]()
![]()
5.3.4 验证要点
[ ] 地图加载后,各省份呈现不同颜色深浅
[ ] 用户数最多的省份颜色最深
[ ] 切换浏览器筛选器,地图颜色分布相应变化
[ ] 无数据的省份显示为默认颜色(或灰色)
5.4 Step 4:完整蓝图整合
完成以上三个步骤后,您的蓝图应包含以下完整的数据流:
5.4.1 大屏切换链路![]()
5.4.2 省份点击下钻链路![]()
5.4.3 热力渲染链路![]()
六、关键技术深度解析
6.1 全局变量管理策略
本实验使用了多个全局变量进行跨节点数据共享:
| 变量名 | 存储内容 | 写入节点 | 读取节点 |
|---|---|---|---|
window.GLOBAL_SELECTED_BROWSER | 当前选中的浏览器 | 浏览器参数接收 | 各SQL请求节点 |
window.globalProvinceName | 点击的省份简称 | 提取地区名称 | 省份核心指标查询 |
window.globalProvinceAdcode | 省份名称→adcode映射 | 提取adcode映射表 | 地图数据与用户数映射 |
设计原则:
✅单一职责:每个变量只存储一种数据
✅命名规范:使用
GLOBAL_前缀标识全局变量✅生命周期:在页面加载时初始化,在交互事件中更新
6.2 分支判断节点的条件表达式
本实验中的分支判断使用简单的等值判断:
return data.id == 1;进阶用法:
| 场景 | 表达式 | 说明 |
|---|---|---|
| 多Tab切换 | return data.id; | 直接返回ID,配合多分支 |
| 范围判断 | return data.value > 100; | 数值阈值判断 |
| 复合条件 | return data.id == 1 && data.type == 'market'; | 多条件组合 |
| 字符串匹配 | return data.name.includes('北京'); | 模糊匹配 |
6.3 地图热力层的数据驱动原理
Max地图组件的热力渲染基于数据驱动模式:
原始数据(省份+用户数) │ ├──→ 数据映射(匹配adcode) │ ├──→ 颜色映射(value → 颜色深浅) │ 平台内置算法:根据value范围自动分配颜色梯度 │ └──→ 渲染层(Canvas/SVG绘制)颜色映射算法(平台内部实现):
自动计算数据的最大值和最小值
将数值范围映射到颜色梯度(如浅蓝 → 深蓝)
支持自定义颜色主题
七、常见问题与解决方案
Q1:Tab切换时,两个大屏内容重叠显示
原因:图层可见性配置错误,或两个组未正确分组。
解决方案:
确认"市场分析组"和"用户画像组"是独立的图层组
检查分支判断的两个分支是否分别配置了"显示"和"隐藏"
初始状态下,确保只有一个组是可见的
Q2:点击地图省份,指标卡数据不更新
排查步骤:
在"提取地区名称"节点添加
console.log(data),确认是否接收到点击事件检查
window.globalProvinceName是否正确赋值在"省份核心指标查询"节点添加
console.log(sql),确认SQL语句正确检查数据库中该省份+浏览器的组合是否有数据
Q3:地图热力层不显示颜色
排查步骤:
确认"提取adcode映射表"节点是否正确执行(检查控制台日志)
检查
window.globalProvinceAdcode是否包含有效的映射关系在"地图数据与用户数映射"节点添加调试代码,确认输出格式为
{ name, value, area_id }检查
area_id是否为数字类型(字符串会导致匹配失败)
Q4:省份名称映射失败(如"内蒙古自治区"无法匹配)
原因:简化名称的逻辑未能覆盖所有特殊情况。
解决方案:
在
specialMap中添加缺失的映射或在简化名称逻辑中增加更多的正则替换规则
Q5:切换浏览器后,地图热力图未更新
原因:热力渲染链路未与浏览器筛选器联动。
解决方案:
确认"各省份用户数查询"节点的触发源包含"浏览器筛选器"
确认SQL中使用了
window.GLOBAL_SELECTED_BROWSER变量
八、实验总结与进阶思考
8.1 核心收获
通过本实验,我们完成了从数据展示到交互洞察的完整闭环:
| 功能模块 | 技术要点 | 业务价值 |
|---|---|---|
| Tab导航切换 | 图层可见性控制 + 分支判断 | 单文件管理多屏,降低维护成本 |
| 省份点击下钻 | 事件驱动 + 动态SQL + 数据分发 | 地理维度深入分析 |
| 热力图渲染 | GeoJSON解析 + adcode映射 + 数据驱动着色 | 直观展示地理分布差异 |
8.2 可扩展的交互场景
基于本实验的技术框架,可以进一步扩展:
| 扩展场景 | 实现思路 |
|---|---|
| 双击下钻到城市 | 地图组件支持多级下钻,配置城市级GeoJSON |
| 时间轴播放 | 添加时间筛选器,实现数据随时间变化的热力图动画 |
| 多指标切换 | 添加指标切换按钮,热力图按不同指标(用户数/时长/收入)渲染 |
| 联动高亮 | 点击省份时,同时高亮该省份在所有图表中的数据 |
| 数据下钻弹窗 | 点击省份后弹出模态框,展示该省份的详细用户画像 |
8.3 性能优化建议
| 优化点 | 方案 | 预期效果 |
|---|---|---|
| SQL优化 | 为browser_name+province添加联合索引 | 查询速度提升60%+ |
| 数据缓存 | 对adcode映射表进行本地缓存 | 避免重复解析GeoJSON |
| 懒加载 | 市场分析组数据延迟加载 | 首屏加载时间减少40% |
| 防抖处理 | 地图点击添加防抖(300ms) | 避免快速点击导致多次请求 |
8.4 发布与分享
完成所有配置后,点击"发布"按钮:
打开发布分享开关
复制分享链接
在浏览器中打开链接,即可在线观看
示例分享链接格式:
http://47.109.66.142:30887/#/dataScreen/release?shareId=cb73b29223c74387a7cb02880d010c0b九、完整代码速查表
9.1 省份名称映射代码
const specialMap = { '北京市': '北京', '天津市': '天津', '上海市': '上海', '重庆市': '重庆', '广西壮族自治区': '广西', '内蒙古自治区': '内蒙古', '西藏自治区': '西藏', '宁夏回族自治区': '宁夏', '新疆维吾尔自治区': '新疆', '香港特别行政区': '香港', '澳门特别行政区': '澳门' }; let provinceName = data.name; if (specialMap[provinceName]) { provinceName = specialMap[provinceName]; } else { provinceName = provinceName.replace(/(省|自治区|市)$/, ''); } window.globalProvinceName = provinceName; return provinceName;9.2 省份核心指标SQL模板
const selectedProvince = window.globalProvinceName; const selectedBrowser = window.GLOBAL_SELECTED_BROWSER; const sql = ` select 'total_users' as name, sum(user_count) as value from labs.user_profile_stats where browser_name = '${selectedBrowser}' and province = '${selectedProvince}' union all select 'avg_age' as name, round(sum(age * user_count) / sum(user_count), 0) as value from labs.user_profile_stats where browser_name = '${selectedBrowser}' and province = '${selectedProvince}' union all select 'high_edu_ratio' as name, round(sum(case when edu in ('本科', '硕士及以上') then user_count else 0 end) * 100.0 / sum(user_count), 2) as value from labs.user_profile_stats where browser_name = '${selectedBrowser}' and province = '${selectedProvince}' union all select 'high_income_ratio' as name, round(sum(case when income in ('5001~8000元', '8001~12000元','12000元以上') then user_count else 0 end) * 100.0 / sum(user_count), 2) as value from labs.user_profile_stats where browser_name = '${selectedBrowser}' and province = '${selectedProvince}' `; return sql;9.3 adcode提取代码
function extractAdcodeAndName(data) { if (!data || !Array.isArray(data.features)) { console.error('无效的地图数据格式'); return {}; } const nameToAdcode = {}; data.features.forEach(feature => { const props = feature.properties; if (props && props.adcode && props.name) { nameToAdcode[props.name] = props.adcode; } }); return nameToAdcode; } const mapping = extractAdcodeAndName(data); window.globalProvinceAdcode = mapping; return mapping;9.4 热力数据映射代码
function convertToMapData(data) { if (!Array.isArray(data) || data.length === 0) return []; return data.map(item => { const provinceName = item.name; let area_id = window.globalProvinceAdcode[provinceName]; if (!area_id) { const simplifiedName = provinceName.replace(/省|市|自治区|特别行政区|回族|壮族|维吾尔|藏族|苗族/g, ''); for (const fullName in window.globalProvinceAdcode) { if (fullName.includes(simplifiedName)) { area_id = window.globalProvinceAdcode[fullName]; break; } } } if (!area_id) area_id = "000000"; return { name: provinceName, value: parseFloat(item.value) || 0, area_id: Number(area_id) }; }); } return convertToMapData(data);版权声明:本文为实验平台实验指导内容的技术总结,仅供学习交流使用。
发布日期:2026年6月
