跳到主要内容

暗黑模式访客地图排障记录

问题背景

首页左侧使用了第三方 MapMyVisitors 访客地图组件。

明亮模式下显示正常,但暗黑模式连续出现了这些问题:

  • 地图看起来只有海洋和少量访客点,陆地几乎消失。
  • 地图外层容器、内层地图区域、海洋底色之间有明显分层。
  • 暗黑模式下绿色访客点不够清楚。
  • 用户要求只修暗黑模式,明亮模式保持不变。

表面看这像是一次普通调色,但后续排查证明,根因不只是颜色值。

最初现象

用户的反馈很集中:

  • 暗黑模式看不到陆地。
  • 刷新后问题依然存在。
  • 明亮模式没有问题。

这组现象说明问题大概率不在全站主题切换逻辑,而在这个第三方组件自己的暗黑渲染路径里。

如果是全局主题或页面布局的问题,亮色模式通常也会被波及。但这里亮色模式一直正常,所以排查重点需要收缩到组件本身。

第一轮排查:先排除本地样式覆盖

先检查了首页相关文件:

  • src/pages/index.js
  • src/pages/index.module.css

重点看了几类风险点:

  • 有没有对地图做 filter
  • 有没有对地图做反色、亮度、对比度处理
  • 有没有全局 SVG 样式误伤第三方地图内部节点

结果是:

  • 本地样式主要只是圆角、边框、背景和阴影。
  • 没有会直接把陆地盖掉的滤镜。
  • 没有发现明显的全局样式误伤。

这一轮的结论是:问题不像是“我们自己的 CSS 把地图遮住了”,更像是第三方地图组件自身在暗黑模式下没有稳定把陆地表现出来。

第二轮排查:确认第三方脚本参数到底控制什么

首页里这个组件通过切换脚本 URL 参数来区分亮暗模式,参数包括:

  • cl
  • co
  • ct
  • cmo
  • cmn

最初可以猜测:

  • cl 对应 land,也就是陆地
  • co 对应 ocean,也就是海洋

但不能只靠命名猜,因为第三方服务未必完全按直觉工作。

所以后续改成直接读取第三方脚本源码和生成结果来验证。

第三轮排查:读取 map.js 源码

通过抓取第三方 map.js 源码,发现这个组件不是单纯靠一层 SVG 把世界地图完整画出来,而是分成了两层。

第一层是背景图层。

脚本里会根据参数生成一个背景图地址,形式类似:

//mapmyvisitors.com/generated_content/backs/bg-w_320-co_xxxxxx-cl_xxxxxx.png

这说明:

  • cocl 会先生成一张底图 PNG
  • 这张图负责最底层的海洋和陆地

第二层是动态层。

脚本随后又会异步请求 widget_call_home.js,再用 jvectormap 在上层绘制:

  • 地图交互层
  • 访客点
  • 标签和统计内容

关键结论是:

陆地可见性并不完全取决于上层 SVG 是否存在,更取决于底层背景图是否稳定加载,以及陆地和海洋之间是否有足够对比。

这也解释了用户看到的现象:上层访客点还能出现,但底层陆地一旦不稳定,视觉上就像整张图只剩海洋和几个点。

第四轮排查:验证 clco 的真实作用

为了避免只看变量名做判断,又直接抓取了第三方生成的背景图,并对颜色结果做了比对。

最终确认:

  • cl 确实控制陆地颜色
  • co 确实控制海洋颜色

这一步排除了“参数理解反了”的可能。

也就是说,陆地不可见并不是因为把海洋和陆地颜色写反了,而是两个更深层的问题叠加在一起:

  • 暗黑配色在小尺寸地图上对比不够
  • 组件过度依赖第三方远端生成的底图

为什么单纯改颜色不够

中间尝试过几组不同的暗黑参数,包括:

  • 更浅的陆地色
  • 更深的海洋色
  • 更亮的文本色
  • 更明显的访客点颜色

这些改动能改善观感,但不能彻底解决问题。

原因有三个:

  • 用户刷新后问题仍然存在,说明不是一次性的状态残留
  • 第三方底图来自远端动态生成,表现并不完全可控
  • 即使参数理论上合理,也不能保证用户端每次都得到一致结果

所以如果继续只依赖第三方远端底图,这个问题会一直处于“理论上应该正常,但实际不稳定”的状态。

最终方案:把暗黑模式陆地图层本地化

最后采用了一个更稳定的方案。

保留第三方组件负责的动态部分:

  • 访客点
  • 统计文字
  • 交互层

只把暗黑模式下的底层地图背景本地化。

这样做以后:

  • 陆地是否显示,不再依赖第三方远端底图的即时表现
  • 亮色模式完全不动
  • 第三方动态数据仍然保留

对应新增的本地资源是:

  • static/img/mapmyvisitors-dark-bg.png

对应样式处理在:

  • src/pages/index.module.css

这里的核心思路是把不稳定的部分收缩掉,只保留第三方组件真正有价值的动态能力。

额外处理:修复主题切换残留

除了底图本身,另一个潜在风险是明暗主题切换时,第三方脚本未必会完整重建。

所以在首页组件里额外做了处理,让访客地图在主题切换时重新挂载。

对应文件:

  • src/pages/index.js

这样做的目的是:

  • 从亮色切到暗色时,第三方脚本重新初始化
  • 避免沿用上一种主题下的残留 DOM 和旧状态

视觉收尾:让地图和整站暗色风格统一

陆地恢复之后,问题就从“功能不可用”变成了“视觉还不够协调”。

用户后续提出了两个很关键的审美反馈:

  • 海洋颜色和地图内层、外层容器颜色不统一
  • 绿色访客点不够清楚

所以又做了两轮收尾优化。

统一海洋色和容器色

把暗黑模式下的海洋色抽成统一变量:

--dark-map-sea: #1c2836;

外层容器和内层地图容器都使用同一个海洋底色,这样视觉上就不会再像两层分离的盒子,而是更像一整张地图自然嵌在侧边卡片里。

提升访客点辨识度

暗黑模式下又对访客点做了进一步优化:

  • 历史访客点改成更干净的薄荷绿
  • 最近访客点使用更清晰的暖红色
  • 点位描边改得更亮
  • 额外加了轻微发光,避免点位在深色海洋上发闷

这样调整以后,不管点落在海洋上还是陆地上,都更容易看清。

为什么这个方案更可靠

最终方案的价值不只是“现在看起来好了”,更在于它在工程上更可控。

主要有四点:

  • 把不稳定依赖缩小了,第三方远端底图不再决定陆地是否可见
  • 风险被限制在暗黑模式里,亮色模式保持原样
  • 问题被拆层处理,背景层和动态层职责更清楚
  • 后续继续微调时,只需要改本地样式和暗黑参数

本次涉及的关键文件

  • package.json
  • package-lock.json
  • src/pages/index.js
  • src/pages/index.module.css
  • static/img/mapmyvisitors-dark-bg.png

验证方式

本次修改完成后,执行了:

npm run build

构建通过,说明:

  • 首页地图组件代码可正常打包
  • 本地图像资源路径有效
  • Docusaurus 构建没有被这次改动破坏

最终结论

这次问题的关键不在于“颜色没调对”,而在于最初如果只把它看成普通配色问题,就会一直停留在试错式调参。

真正有效的修复路径是:

  • 先搞清楚第三方组件到底怎么渲染地图
  • 识别出底图层和动态层的职责差异
  • 把最不稳定的暗黑底图层本地化
  • 再做配色统一和可读性收尾

最终得到的不是一次碰巧成功的调色,而是一套有证据、有分析路径、也能持续维护的修复方案。