开始
之前写过一篇 Three.js 实现 3D 地图可视化,单独讲了浙江省那个版本怎么搭。这次把整块大屏也一起整理下,重点还是放在正中间那张可交互的 3D 中国地图上,它是这个项目里最花时间、也最值得说的部分。
这是一块数据中心的监测大屏,按 1920 × 1080 的设计稿做,运行时再等比缩放铺满屏幕。结构上就是大屏里很常见的那种,中间一个主视觉,左右两栏数据面板。
这篇分两部分写:前半段过一遍大屏整体长什么样,后半段重点拆中间那张地图是怎么做出来的。
🔗 在线体验地址:可视化大屏 · 3D 地图
这套大屏 + 中央可交互 3D 地图的完整源码有偿提供,微信
jl643546122。
第一部分 · 大屏整体
1. 这张大屏长什么样
- 顶栏放标题、左上角运行状态、右上角实时时钟和日期,上面叠了一条慢慢扫过去的光带。
- 左栏从上到下是资源利用率排行、核心指标总览、区域节点容量。
- 中栏是 3D 中国地图,四角有装饰角标,配了标题和底部的模式切换按钮。
- 右栏是负载类型占比、能耗趋势分析、各经济产值。
背景是几层径向渐变叠上细网格线堆出来的,深蓝底色,撑科技感。
2. 大屏怎么适配不同屏幕
所有内容都按 1920×1080 的设计稿把位置和尺寸写死,外面再套一层缩放容器。它会拿当前窗口的宽高去比设计稿,取较小的那个比例整体缩放,再居中。这样不管屏幕多大,画面都是完整等比的,不会变形也不会裁掉。每个面板自己完全不用操心屏幕适配的事,是大屏开发里挺通用的一个套路。
3. 面板数据是怎么来的
每个面板的数据都是各自去后台拉的,大部分还会每隔 3 秒自动刷新一次,做出实时监测的感觉。拉数据的时候要是失败了,会先把上一次的数据继续显示着,不会让大屏闪一下白,那样很难看。
开发阶段后台接口还没好,就在浏览器里拦截这些请求、用工具现造假数据顶上,效果和真接口一模一样。等真后台好了,把接口换上就行,页面这边几乎不用动。
4. 两侧面板
左右六个面板长得是一套样式:标题加内容区,加载中、出错、没数据这几种状态也都统一处理好了。
左栏:
- 资源利用率排行:列出占用最高的几个集群,名次加用量加一条进度条。
- 核心指标总览:六张卡片,在线服务器、运行机柜、GPU 利用率、存储容量、出口带宽、实时告警,每张配个六边形图标和数值。
- 区域节点容量:双柱状图,算力负载对比存储占用。
右栏:
- 负载类型占比:一个环形图加图例,外面又叠了两圈装饰环在慢慢反向转。
- 能耗趋势分析:月度能耗的折线面积图。
- 各经济产值:左边三产指标,右边是一颗手画的「经济地球」,球面经纬网自转、热点脉冲、还做了前后景深,外面再套两圈轨道环,中心放总产值数字。
这几个面板基本把大屏里常见的组件都覆盖了:排行、指标卡、柱状、环形、折线,还有自定义画的图形。
第二部分 · 中央 3D 地图
这是整块大屏里最花心思的部分。下面按搭建的顺序,一块一块讲它是怎么做出来的、做出来什么效果。
用到的三方库
| 三方库 | 功能说明 |
|---|---|
three | 3D 渲染框架 |
OrbitControls | 相机控制,能缩放和旋转 |
EffectComposer + UnrealBloomPass | 辉光后处理,让该亮的地方真的亮起来 |
gsap | 动画库,管入场推进、光环弹出、柱体生长这些 |
| Web Mercator 投影 | 把经纬度换算成平面上的坐标 |
地图数据从 阿里云 DataV 下载,是带经纬度的 GeoJSON,全国、各省、各市分开存,下钻的时候按需加载。
一步步把这张地图搭起来
1. 先把舞台铺好:背景、雾、相机、灯光
- 背景用一个纯色,再叠一层同色的雾,让地图远端和延伸出去的地板慢慢化进背景里,不会有生硬的边。
- 相机用透视相机,从斜上方俯视地图中心。
- 灯光放了三盏:一盏打底,一盏从正上方照(不然鼠标划过的时候上下半部分会一明一暗),还有一盏按表面朝向均匀给光、不衰减,保证各处亮度差不多。
- 地图本来是按平面建的,最后整体往后倒 90°,平放到水平面上。
2. 动态地板网格
地图和光环底下铺了一层科技感的地板(上图是单独把地图和光环藏起来后的样子):大网格线加交点上的小加号,每个大格再细分成更小的格子,默认是透明的,运行时每隔一会儿随机点亮一批,渐显渐隐,看起来像数据在地板上流动。
3. 外缘旋转光环
地图外圈那几道会转的环(上图同样把地图藏掉,只留环和地板):三道断成几段、段间留缝的环,越往外越细越淡,再加一道带 12 个刻度的时钟环。每道环转的速度和方向都不一样,叠在一起就有层次。入场的时候它们还会带点回弹,一道一道弹出来。
4. 主体:中国地图本体
这是地图的核心,做了这么几件事:
- 投影:地图数据是经纬度,得先换算成平面坐标。这里所有层级(全国、省、市)都缩放到同一个目标大小,这一步是后面下钻能平滑放大的关键。
- 逐省挤出:把每个省的轮廓拉出一定厚度,变成一块块立起来的 3D 板,飞地和中间的空洞也都处理了。
- 侧壁渐变:每块板的侧面不是纯色,而是从底到顶做了青蓝渐变,顶部还带一圈淡淡的辉光,立体感主要靠这个。
5. 边界线和内阴影
每个省描了三种线:底部贴地的暗色轮廓、顶部发光的省界、还有一条平时透明、鼠标移上去才淡入的高亮描边。
比较费劲的是内阴影,就是让地图边缘压暗、中间透亮的那层效果。它的做法是把全国所有省份当成一整张图来算阴影,只让阴影从国境的最外缘往里渗,省与省之间的内部边界不会冒出多余的暗边,最后贴回地图顶面。这块当时调了挺久,但加上之后整张图一下就有"体积"了,不再是平的。
6. 跟随地图的标注
上图里 北京 86%、上海 82% 那些卡片,其实是普通的网页文字标签,不是 3D 物体。做法是记下每个标签在 3D 世界里对应的位置,再每一帧用相机算出它现在该出现在屏幕的哪个像素上,实时挪过去。这样标签既清晰好排版,又能严丝合缝地跟着地图一起转、一起缩放。
全国这一层显示 6 个枢纽城市的卡片,带利用率百分比;下钻进省里之后,就自动换成各个市、区县的名字,定位在每块区域的中心。
底部四个模式
地图底部那排「飞线 / 柱状图 / 粒子 / 图表动画」是四种叠加效果,点一下就切换,本质是控制不同图层显示还是隐藏。
飞线模式
在几个枢纽城市之间拉起一道道弧线,弧线两端淡、中间亮,上面还跑着一个"彗星头"沿着弧线循环飞,做出城市间数据互联的感觉。
柱状图模式
在每个枢纽城市头顶竖一根数据柱,柱子高低代表数值大小,柱底套一圈会旋转、扩散的特效光环。柱子是从地里"长"出来的动画。这个模式会把城市卡片藏掉,把画面让给柱子。
粒子模式
满屏撒一些向上飘的粒子,飘到顶就回到底下重新来,做出数据上浮那种氛围。这个模式飞线、柱子、标签都关掉,画面最干净。
图表动画模式(全开)
飞线、柱子、粒子、标注全部打开。上图里弧光环、发光地图、跟随卡片、飞线、数据柱、粒子能同时看到,是信息量最大的状态。
交互:高亮和逐级下钻
悬浮高亮
鼠标移到哪个省,哪个省就亮一下,顶面提亮、边缘描边淡入,指针旁边还会弹个省名的小提示;移走就复位。
点击下钻 / 右键返回
这是地图最实用的能力。点一个省,就钻进它的市级地图(上图就是点开安徽省之后的 16 个地级市),再点继续钻到区县级,右键或者点空白处返回上一级。几个细节:
- 防误触:如果你按下到松开之间鼠标挪动了一点,就当成是在拖着旋转地图,不会误触发下钻。
- 按需加载:钻进哪个区域,才去加载那个区域的地图数据,不会一开始全部加载。
- 平滑放大:因为前面说过所有层级都缩放到同一个大小,所以下钻看起来就是顺滑地放大填充,没有突兀的跳变。
- 联动信息:每次下钻,地图左上角的面包屑路径(上图里的「全国 / 安徽省」)和它下面那张省份详情卡都会跟着更新;底部的模式 Tab、两侧的数据面板也都还在,整屏是联动的。
相机控制
滚轮能缩放、拖拽能旋转,但限制了角度(不让你转到地图背面去),也不让平移,让地图始终围着中心转,怎么转都不会"丢"。
收尾:入场动画、辉光、资源回收
- 入场动画:相机从一个很远的位置慢慢推进到默认视角,差不多 2 秒,光环也在这期间一道道弹出来;这段时间锁住鼠标操作,放完再交还控制权。
- 辉光:给发光的边界、飞线、粒子、柱子做一层辉光后处理,让它们真的"亮"起来,而不只是颜色浅。
- 资源回收:下钻切换地图、或者整个组件关掉的时候,把用过的 3D 模型、材质、贴图、事件监听都释放干净,不然时间一长内存和显存会慢慢漏。
它是怎么"活"起来的
屏幕上看起来一直在动的那些东西——外圈光环在转、地板格子随机闪、地图整体轻轻上下浮、飞线彗星在飞、粒子在升、柱底光环在扩散、标签跟着地图挪——其实都是每一帧重新算一遍位置再画出来的,一秒几十帧,连起来就成了动画。
总结
整理下来,这块大屏想做的事其实就两件:把数据讲清楚,把画面做好看。
数据这边,靠等比缩放适配各种屏幕、靠每个面板自己定时刷新、靠开发期假数据顶上,让它既能随便增减模块,又能平顺地接上真后台。
画面这边,就是中间这张地图,从铺场景、地板、光环,到立起地图、描边界做内阴影,再到标注、各种叠加特效、辉光、交互,一层层堆上去。
说实话难点不在哪个单点,而在细节调试和各层之间的配合,每一处都得慢慢试。如果只想看单省版本怎么从零搭,可以回去看 Three.js 实现 3D 地图可视化 那篇。