MapLibre 中使用的字体:浏览器本地字体、Web 字体与 Glyphs 字体切片详解

核心结论(TL;DR)

  • MapLibre GL JS 自 5.11.0 版本起支持浏览器本地字体:当样式(Style)中省略(omit)glyphs 配置时,地图文字直接使用客户端系统字体渲染,无需发起网络请求。该特性目前仅 GL JS 支持,MapLibre Native(Android / iOS)暂不支持。
  • MapLibre 共有 3 种字体加载方式:浏览器本地字体、font-faces Web 字体、glyphs 服务端字体切片(SDF + PBF 格式)。
  • 是否触发 glyphs 网络请求,取决于 text-font 配置的字体能否在客户端本地命中,与数据源类型(矢量瓦片 / GeoJSON)没有直接关系。
  • text-font 是一个字体栈(Font Stack)数组,语义与 CSS font-family 一致:从前往后匹配,命中即用,实现优雅降级。
  • 配置中文 Windows 字体必须使用字体真实名称(如 SimHei、FangSong),而不是中文别名("黑体"、"仿宋"),否则配置不生效。
  • 中文字体文件体积巨大(仿宋约 11 MB,方正黑体_GBK 约 10 MB,部分字体可达 70 MB),glyphs 按需切片仍是保证跨端渲染一致性的最佳实践。glyphs 切片可以不用,但不能没有。

背景:为什么地图文字会渲染不出来?

在早期的 Mapbox GL JS / MapLibre 中,若样式未正确配置 glyphs 字体切片服务,symbol 图层(符号图层)的标注文字会直接"消失"——这是 WebGIS 开发中最常见的渲染问题之一。其根源在于:地图引擎无法凭空获得字形数据,必须从浏览器本地字体、Web 字体或服务端 glyphs 切片三者之一获取。

本文基于 ZeroGIS Server 团队在矢量瓦片服务发布与地图配图工具开发中的实践经验,系统梳理 MapLibre 字体加载机制、常见配置陷阱与选型建议,并对照 MapLibre 官方样式规范(Style Spec)给出可验证的依据。

一、MapLibre 支持浏览器本地字体吗?

支持。根据 MapLibre 官方样式规范,MapLibre GL JS 从 5.11.0 开始支持"省略 glyphs 使用本地字体"(omit to use local fonts)。

MapLibre 共有 3 种字体加载方式,按"离客户端远近"排列如下:

加载方式数据来源网络请求渲染一致性适用场景
浏览器本地字体客户端操作系统已安装字体无依赖客户端环境,跨端可能不一致内网系统、节省带宽、标注要求不高
Web 字体(font-faces)样式中指定的网络字体文件(.ttf 等)一次性整包下载较高字符集较小的语种(GL JS 暂不支持,见第七节)
Glyphs 字体切片(glyphs)服务端按需生成的 SDF 字形切片(PBF 格式)按码位区间增量请求最高,所有客户端一致面向公网的生产环境地图

三者并不互斥:MapLibre 会根据样式配置与字符类型决定实际走哪条链路(判定规则见第二节)。

"omit to use local fonts" 是什么意思?

官方文档在 glyphs 属性的 SDK 支持表中标注了 "omit to use local fonts"(GL JS 5.11.0 起)。结合上下文,其准确含义是:

当样式中省略(omit)glyphs 属性时,文字将使用本地(客户端系统)字体渲染。

它不是"取消使用本地字体",恰恰相反——是"省略 glyphs 配置,即可启用本地字体"。官方规范原文的表述是:如果设置了 glyphs,text-field 的文字将基于 text-font 指定的字体栈,从该 URL 加载字形;否则,字体由 text-font 根据本地环境决定。

二、何时会触发 Glyphs 网络请求?矢量瓦片与 GeoJSON 有区别吗?

结论:矢量瓦片和 GeoJSON 数据源都可能触发 glyphs 请求,真正决定是否请求的是三个因素——text-font 字体能否在本地命中、样式是否配置了 glyphs、以及 localIdeographFontFamily 的取值。

MapLibre 的字体解析判定流程如下:

  1. CJK 表意字符(中文 / 日文 / 韩文):默认由 localIdeographFontFamily(默认值 sans-serif)指定的本地系统字体渲染,跳过 glyphs 请求;
  2. 非 CJK 字符:若样式配置了 glyphs URL,则按 text-font 字体栈向服务端请求切片;若样式省略了 glyphs(GL JS 5.11.0+),则走浏览器本地字体;
  3. localIdeographFontFamily: false:强制关闭本地渲染,CJK 字符也必须从网络加载 glyphs 切片。官方文档明确提示:这会显著变慢(much slower)。

实测案例

场景text-font 配置字体在 Windows 本地是否命中实际行为
矢量瓦片服务默认字体["Open Sans Regular", "Arial Unicode MS Regular"]否(Windows 默认不存在)触发 glyphs 网络请求
GeoJSON 数据源图层字体["FangSong", "SimHei"]是(仿宋、黑体为 Windows 自带)本地渲染,不发起网络请求
强制 localIdeographFontFamily: false任意忽略本地命中结果无论本地是否有该字体,都强制从网络加载 glyphs 切片

可见"矢量瓦片触发了请求、GeoJSON 没触发"只是表象:前者配置的字体本地没有,后者配置的字体本地有,与数据源类型本身无关。

三、多个 Symbol 图层使用不同字体时,Glyphs 如何加载?

对于 CJK 字符,MapLibre 默认走 localIdeographFontFamily(默认 sans-serif)用系统字体渲染,从而跳过 glyphs 请求;对于非 CJK 字符,MapLibre 会为每个不同的字体栈分别发起对应的 glyphs 请求——配置了多少种字体栈,就会发送多少种请求,不同字体栈之间互不共享缓存。

因此在生产环境中,应尽量收敛样式中的字体栈数量,避免为每个 symbol 图层配置互不相同字体带来的请求放大。

四、为什么 text-font 是数组?——字体栈的降级机制

text-font 配置为数组,例如:

"text-font": ["FangSong", "SimHei"]

语义是:优先使用仿宋(FangSong),若客户端或服务端没有仿宋,则退而采用黑体(SimHei)。这与 CSS font-family 的回退(fallback)语义完全一致,是一种优雅降级(graceful degradation)设计。

需要注意服务端的实现细节:生成 glyphs 切片时,并不是把两个字体混合切到一个文件里,而是按字体栈从前往后逐个匹配——请求某个码位区间时,先查字体栈第一项是否覆盖该字形,命中即返回该字体的切片,未命中再尝试下一项。

五、为什么 text-font 指定"黑体"不生效?——字体真实名称与中文别名

因为 MapLibre 需要的是字体的真实名称(Font Family / PostScript Name),而不是 Windows 中显示的中文别名。"黑体"的真实名称是 SimHei,对应文件 simhei.ttf。

测试中为 symbol 图层设置 text-font: ["黑体"] 不会生效。"黑体"只是 Windows 系统中面向用户显示的中文本地化别名(display name),字体匹配时必须使用其真实名称。

Windows 常用中文字体名称对照表

中文显示名真实名称(text-font 应填写的值)字体文件名文件格式
宋体SimSunsimsun.ttcTTC
黑体SimHeisimhei.ttfTTF
仿宋FangSongsimfang.ttfTTF
楷体KaiTisimkai.ttfTTF
微软雅黑Microsoft YaHeimsyh.ttcTTC

常见字体文件格式

格式全称说明
TTFTrueType Font最常用的字体格式
OTFOpenType Font基于 PostScript 曲线的字体格式,其次常用
TTCTrueType CollectionTrueType 字体集合,一个文件打包多个字体
OTCOpenType CollectionOpenType 字体集合

两点补充:

  • 字体文件名不等于字体真实名称:simfang.ttf 实际是 FangSong(仿宋),simhei.ttf 实际是 SimHei(黑体);
  • Windows 字体目录为 C:\Windows\Fonts,可根据需要将字体文件复制出来,供服务端切片使用。

六、能用浏览器本地字体了,还需要 Glyphs 切片字体吗?

有必要。 两者解决的是不同问题:

  • 浏览器本地字体的最大价值是节省带宽、加快首屏渲染,是一种非常好的功能特性;
  • 但它依赖客户端能力:不同操作系统、不同浏览器安装的字体集合不同,一旦客户端缺少对应字体,渲染结果就会产生差异。

对于对视觉效果要求较高、需要保证所有用户看到完全一致的地图呈现的场景(如政务、企业品牌地图),通过 glyphs 服务端切片统一提供字形,才能保证渲染一致性。

七、有 font-faces 了,还需要保留 Glyphs 切片吗?

有必要,而且截至 2026 年 9 月,glyphs 切片仍是 Web 端唯一完整可用的服务端字体方案。

  1. 中文字体体积巨大:英文字体通常很小,中文字体动辄数十 MB——仿宋约 11 MB,方正黑体_GBK 约 10 MB,实践中还见过 70 MB 的字体文件(作者实测)。Web 字体(font-faces)是一次性整包下载,网络开销巨大;
  2. glyphs 是真正的增量加载:切片以 256 个 Unicode 码位(code point)为一个区间(range) 按需请求(例如基础拉丁区为 0-255),中文地图只会下载画面中实际出现的字符所在区间;
  3. 时效性提示:font-faces 属性目前仅在 MapLibre Native(Android 11.13.0+、iOS 6.18.0+)中支持,MapLibre GL JS 尚未支持(见官方规范标注的 issue #6637)。

因此结论是:MapLibre 的 glyphs 字体切片可以不用,但不能没有。

八、ZeroGIS Server:包含零门槛的动态字体切片方案

自建 glyphs 切片服务门槛较高,ZeroGIS Server 已内置集成 glyphs 网络字体切片功能,支持动态切片:只需将 .ttf 字体文件复制到 fonts 文件夹,即完成字体切片接入,上手零门槛。

ZeroGIS Server 是一款可替代 GeoServer / MapServer 的地图服务发布与在线配图工具,详情请参见官网 ZeroGIS Server (https://www.newgis.top/)open in new window。

常见问题(FAQ)

Q1:MapLibre 哪个版本开始支持浏览器本地字体? A:MapLibre GL JS 5.11.0。当样式省略 glyphs 属性时即启用本地字体,该特性在官方样式规范的 SDK 支持表中标注为 "omit to use local fonts";MapLibre Native(Android / iOS)暂不支持。

Q2:加载 GeoJSON 图层为什么不发 glyphs 请求? A:因为该图层 text-font 配置的字体(如 FangSong、SimHei)在客户端本地命中,或 CJK 字符默认走 localIdeographFontFamily 本地渲染,与数据源类型无关。

Q3:如何强制 MapLibre 走服务端 glyphs 切片? A:将 Map 构造参数 localIdeographFontFamily 设为 false。此时无论本地是否有对应字体,CJK 字符都会从网络加载 glyphs 切片(官方提示:更慢)。

Q4:text-font: ["黑体"] 为什么不生效? A:应填写字体真实名称 SimHei,"黑体"只是 Windows 的中文显示别名。同理仿宋应填 FangSong。

Q5:text-font 数组的匹配顺序是什么? A:从前往后逐个匹配,命中即用,类似 CSS font-family 的回退语义;服务端切片同样按此顺序匹配返回。

Q6:中文字体文件一般有多大? A:常见中文字体在 10 MB 量级(仿宋约 11 MB、方正黑体_GBK 约 10 MB),部分字体可达 70 MB,因此不适合整包下发,glyphs 按需切片是更优方案。

术语表(Glossary)

术语英文含义
字形Glyph单个字符的图形表达,地图文字渲染的最小单元
字体切片Glyphs Slices按 Unicode 码位区间(每 256 个码位一个区间)切分的字形数据,以 PBF 格式存储
有向距离场SDF (Signed Distance Field)glyphs 切片使用的字形编码方式,可在 GPU 上高效完成缩放、旋转与描边(halo)
字体栈Font Stacktext-font 配置的字体名称数组,按序降级匹配,语义同 CSS font-family
码位Code PointUnicode 字符集 中每个字符的编号,如 U+4E00–U+9FFF 为 CJK 统一表意文字区
表意文字Ideograph泛指中日韩(CJK)表意字符,MapLibre 对其默认采用本地字体渲染
符号图层Symbol LayerMapLibre 样式中负责图标与文字标注的图层类型,文字渲染由 text-field 与 text-font 控制

参考资料与引用来源

  1. MapLibre Style Spec — Glyphs(含 "omit to use local fonts" 的 SDK 支持版本表):https://maplibre.org/maplibre-style-spec/glyphs/open in new window
  2. MapLibre Style Spec — Font-faces(Web 字体与字体解析优先级说明):https://maplibre.org/maplibre-style-spec/font-faces/open in new window
  3. MapLibre GL JS 官方示例 — Use locally generated ideographs(localIdeographFontFamily 用法):https://maplibre.org/maplibre-gl-js/docs/examples/use-locally-generated-ideographs/open in new window
  4. MapLibre Native iOS — Customizing Fonts(CJK 客户端本地渲染机制):https://maplibre.org/maplibre-native/ios/latest/documentation/maplibre-native-for-ios/customizing_fonts/open in new window
  5. 本文原文(微信公众号):https://mp.weixin.qq.com/s/YqJU8HfbPaMv6AoIXYtO4Qopen in new window

本文基于 MapLibre GL JS 5.11.0+ 的字体特性整理;文中字体体积数据为作者实测值。

上次更新: