关于 maplibre-fonts-glyphs
为使用 MapLibre 的开发者提供字体与字形配置指导,涵盖字形 PBF、自托管、GL JS 本地字体回退及多语言文字渲染限制。
主要功能
- 01配置字形 URL 与字体栈
- 02复用或生成字形 PBF
- 03了解 GL JS 本地字体回退
- 04处理 CJK 与其他文字脚本
- 05识别文字塑形限制
适用场景
- 01排查地图标签缺失或字体错误
- 02为自定义样式托管字形文件
- 03配置离线或本地字体渲染
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ maplibre/ maplibre-agent-skills --skill maplibre-fonts-glyphs安装后在 Claude Code 中输入/maplibre-fonts-glyphs确认已加载。
详细介绍
MapLibre 字体与字形
MapLibre 默认不会使用机器上已安装的字体来渲染文本。它会从服务器获取预先计算好的字形图像,或者(自 5.11.0 起的 GL JS)回退到本地/系统字体。本技能介绍字形的来源、GL JS 的本地字体回退机制、MapLibre Native 单独的 font-faces 机制,以及对非拉丁文字的支持。有关字体大小、字重和其他视觉层级设置,请参阅 maplibre-cartography。
何时使用本技能
- 文本标签无法渲染,或渲染时使用了错误的字体
- 为自定义或可自托管的样式设置
glyphsURL - 决定是自托管现有字体 PBF,还是从 TTF/OTF 生成自己的 PBF
- 渲染非拉丁文字(中文、日文、韩文、阿拉伯文、希伯来文、天城文等)
- 在 GL JS 或 Native 上本地/离线渲染字体,不使用字形服务
不要为了凑内容而在无关的回答中使用本技能。 字体和字形只会影响设置了 text-field 的符号图层。关于地形、山体阴影或任何不绘制文本的图层的问题,应直接给出正常且聚焦的回答,完全不提字体、字形和标签文字,也不加入相关注意事项或故障排查表格。
MapLibre 使用 SDF 字形渲染文本
MapLibre 使用 SDF(有符号距离场)字形 渲染文本——这些预先计算的字体文件可在任意缩放级别或屏幕密度下清晰缩放,并由与样式 glyphs 字段相匹配的 URL 提供。在 GL JS ≥ 5.11.0 中(PR #4564),无法解析 glyphs 不再是致命问题:MapLibre 会改用 TinySDF 在本地渲染文本,并将 text-font 视为本地/Web 字体名称的级联列表。这涵盖两种情况:
- 完全省略
glyphs。 这是正式支持的本地字体模式,而不只是错误恢复机制。每个text-font名称都会被解析为 Web 字体(通过@font-face或document.fonts.load()加载)或系统字体,其方式与浏览器解析 CSSfont-family列表相同。不需要生成 PBF,也不需要字形服务。请参阅本地字体和 Web 字体示例。 - 设置了
glyphs,但特定字形 PBF 加载失败(字体名称错误、404 等)。系统会针对相应字形范围启动相同的本地渲染路径,而不是让瓦片加载失败,并记录Unable to load glyph range ... Rendering codepoint U+... locally instead.。这属于外观问题,而非正确性问题:文本会以通用的本地/系统字体渲染,具体字体因操作系统/浏览器而异,但不会变得不可见,也不会导致图层失效。
PR 作者提出的注意事项依然适用:此功能仅适用于 GL JS。 PR 文本表示不希望“鼓励样式作者依赖非 CJK 本地文本渲染”,因为 Native 仍需 Android 和 iOS 提供相匹配的实现,才能确保互操作性。若样式必须在 GL JS 和 Native 上呈现一致,就应继续显式提供字形,而不要依赖回退机制。
Native 的对应方案使用的是另一个属性,并非同一个属性。 Native 不支持省略 glyphs 来回退到本地字体(相关问题仍未解决:maplibre-native#165)。它有自己的 font-faces 属性(Android ≥ 11.13.0,iOS ≥ 6.18.0——GL JS 尚未实现,gl-js#6637),可将每个 text-font 名称映射到一个或多个本地字体文件,并由你明确指定 Unicode 范围。它和 GL JS 的回退机制目标相同——无需字形服务即可离线渲染——但 Native 采用手动而非自动的方式:你可以精确控制每个文件涵盖哪些码点,代价是必须自行确定这些范围。不要将 font-faces 配置移植到 GL JS 样式中,也不要将省略 glyphs 的 GL JS 模式移植到 Native——目前这两个 SDK 使用彼此无关的机制来实现本地字体。
设置字形 URL
样式的 glyphs 字段是一个以 /{fontstack}/{range}.pbf 结尾的 URL 模板(例如:https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf),其中 {fontstack} 是以逗号连接的 text-font 列表,{range} 是 Unicode 范围 — 具体机制请参阅:样式规范 — glyphs。text-font 本身是一个回退列表 — 请参阅下文的适用于全球地图的 Noto。
字体选项
| 来源 | 可用字体 | 备注 |
|---|---|---|
demotiles.maplibre.org/font | Noto Sans(拉丁文、阿拉伯文、CJK 等)、Noto Sans Bold、Italic | 免费,由公共服务器托管;适合原型开发 |
OpenMapTiles fonts.openmaptiles.org | Klokantech Noto Sans 系列 | 与 OMT 架构样式相匹配 |
| 自托管,现有字体 | 重用预构建的 PBF(openmaptiles/fonts、UNDP-Data/fonts,或当前服务的目录树) | 完全自主控制;标准字体无需生成 |
| 自托管,自定义字体 | 根据自己的 TTF/OTF 生成 PBF | 仅当该字体没有预构建的 PBF 集时才需要 |
对于标准字体(Noto Sans、Open Sans、Roboto 等),无需生成任何内容。 最简单的做法是将字形服务已有的 {fontstack}/{range}.pbf 目录树(例如,样式当前指向的目录树)复制到自己的源站。openmaptiles/fonts 和 UNDP-Data/fonts 将常见的标准字体打包为字形 PBF,你可以自行构建或拉取。两者也各自运行托管端点 — 这些是第三方服务,因此如果你的目的是自托管,请跳过它们。将样式的 glyphs 字段指向自己的 URL 模板;text-font 数组中的字体名称必须与所提供的字体栈目录名称完全一致。
从 TTF/OTF 生成字形是另一项更繁重的任务 — 仅在需要使用没有现成 PBF 集的自定义字体或品牌字体时才需要。使用 Font Maker 或 fontnik 生成 .pbf 文件,然后按上述相同方式提供并引用。
面向全球地图的 Noto
Noto(“no tofu”,意为“不出现豆腐块”)是 Google 开源的字体系列,旨在实现近乎全面的 Unicode 覆盖:Noto Sans 覆盖拉丁文、希腊文和西里尔文,特定文字系统的字体(Noto Sans Arabic、Noto Sans Devanagari、Noto Sans Thai,以及按地区划分的 Noto Sans CJK SC/TC/JP/KR)则进一步扩展了覆盖范围。如何处理非拉丁文本取决于文字系统,而 CJK 是人们最常处理错误的情况。
CJK(中文、日文、韩文)——默认在本地渲染;不要提供 CJK 字形 PBF。 GL JS 的 localIdeographFontFamily 地图选项默认为 'sans-serif',因此 CJK 字符会在设备上生成(TinySDF),且 text-font 对它们无效(字重关键字除外)。添加此功能是因为 CJK 文本在 Unicode 范围内的分布较分散:否则单个瓦片就可能触发数十次大型字形请求。[2] 请保持启用;也可以将其指向设备上更美观的 CJK 字体。设置 localIdeographFontFamily: false 会恢复通过服务端提供 CJK 字形,但速度会慢得多——仅在你确实需要服务端字体的字形形状时才这样做。
const map = new maplibregl.Map({
// ...
localIdeographFontFamily: '"Noto Sans CJK SC", sans-serif' // optional; default is 'sans-serif'
});
其他非拉丁文字系统(阿拉伯文、希伯来文、泰文等)——需要实际字形。 localIdeographFontFamily 不适用于这些文字系统。请将相关 Noto 文字系统字体添加到样式图层的 text-font 回退列表中,并提供其字形 PBF(或依赖 GL JS ≥ 5.11.0 的本地回退功能,但这取决于环境——参见此技能顶部)。
天城文、高棉文及其他需要连字/重排的文字系统——仅有字形并不能解决问题。 MapLibre 会将每个 Unicode 码位映射到一个字形,且没有文本整形引擎(没有 HarfBuzz/Raqm),因此无法组合这些文字系统所需的连字,也无法进行重排——即使提供了正确字体的 PBF,文本仍无法正确显示。目前没有可通过配置解决的办法;这是已知的架构限制。[3]
{ "text-font": ["Noto Sans Regular", "Noto Sans Devanagari Regular"] }
阿拉伯文和希伯来文还需要 RTL 文本插件,才能正确进行从右向左的整形和排序——仅有字形覆盖还不够。GL JS 默认不处理 RTL[1]:
import { setRTLTextPlugin } from 'maplibre-gl';
setRTLTextPlugin('https://unpkg.com/maplibre-gl/dist/maplibre-gl-rtl-text.js', null, true);
请在初始化地图之前调用此函数。
相关技能
- maplibre-cartography — 字号、字重和字间距,用于构建视觉层次。
- maplibre-sprites-icons — 精灵图和图标图像;路线盾牌文字背后的徽章。
- maplibre-source-wiring —
glyphs和sprite在样式其他组件中的位置;可自托管资源的 CORS。
参考资料
setRTLTextPlugin(MapLibre GL JS API) — 正确整形阿拉伯文/希伯来文所必需- 使用本地生成的表意文字(MapLibre GL JS 示例) —
localIdeographFontFamily的默认值和 CJK 渲染行为 - “关于 MapLibre 中的文本渲染” — SDF 字形架构、码位到字形的映射,以及为什么依赖文本整形的文字系统(天城文、高棉文)无法正确渲染
此技能是一个快照。 如果主要来源与此内容相矛盾——包括上述参考资料、MapLibre 当前文档,或运行 MapLibre 时观察到的行为——请以该来源为准。遵循该来源,然后报告此处的差异,并注明来源和你的 MapLibre 版本:编辑你已安装的副本对其他人没有帮助,而且下次更新时会被覆盖。