经纬志
首页 / 实战手册 / MapLibre 样式与图层

样式加载失败,地图一直是灰底

先看结论

地图能出现,也能拖动,但只有一个灰色背景,道路、水系、标注全都没有。

最后验证 2026-11-03 · 多技术栈 · 更新 2026-10-29 · 引用本文

现象

控制台给出样式加载失败的信息,map.isStyleLoaded() 始终为 false:

Error: Could not load style: https://styles.example.cn/basic/style.json
    at Style.load (style.ts:673)
Uncaught Error: style is not done loading

同时所有 addLayer 调用都抛错,因为样式还没就绪。

原因

原因网络面板表现
style.json 路径写错或服务未部署404
跨域未放行请求被 CORS 拦截,无响应头
style.json 里 sprite、glyphs 路径不可达style.json 200,但后续 404
JSON 语法错误200,解析报 Unexpected token
内网证书过期net::ERR_CERT_AUTHORITY_INVALID

排查过程

先注册 error 事件,把被静默吞掉的错误打出来。MapLibre 的很多失败 只会通过这个事件通知:

map.on('error', function (e) {
  console.error('地图错误', e.error && e.error.message, e.sourceId, e.tile);
});

然后直接访问样式地址:

fetch('/styles/basic/style.json')
  .then(function (r) {
    console.log('状态', r.status, '类型', r.headers.get('content-type'));
    return r.json();
  })
  .then(function (s) {
    console.log('sprite', s.sprite, 'glyphs', s.glyphs);
  })
  .catch(function (err) { console.error('样式不可用', err); });

解决方案

本地样式放在与页面同源的目录下,sprite 与 glyphs 用绝对路径,避免相对路径按 style.json 所在目录解析而错位:

{
  "version": 8,
  "name": "basic",
  "sprite": "/styles/basic/sprite",
  "glyphs": "/fonts/{fontstack}/{range}.pbf",
  "sources": {
    "base": {
      "type": "vector",
      "tiles": ["/tiles/base/{z}/{x}/{y}.pbf"],
      "minzoom": 0,
      "maxzoom": 14
    }
  },
  "layers": [
    { "id": "bg", "type": "background", "paint": { "background-color": "#f2f4f6" } }
  ]
}

样式确实不可用时,给一个最少可用的内联样式作为兜底, 保证地图先能显示,再异步替换:

var fallbackStyle = {
  version: 8,
  sources: {},
  layers: [{ id: 'bg', type: 'background', paint: { 'background-color': '#e9edf2' } }]
};

var map = new maplibregl.Map({
  container: 'map',
  style: fallbackStyle,
  center: [116.391, 39.907],
  zoom: 11
});

fetch('/styles/basic/style.json')
  .then(function (r) { return r.json(); })
  .then(function (style) { map.setStyle(style); })
  .catch(function (e) { console.error('保留兜底样式', e); });

addLayer 必须等样式就绪。用 load 事件或用 style.load,不要写在构造函数之后:

map.on('load', function () {
  map.addSource('poi', { type: 'geojson', data: '/data/poi.geojson' });
  map.addLayer({ id: 'poi', type: 'circle', source: 'poi' });
});

验证

map.isStyleLoaded() 在 2 秒内变为 true。 底图出现道路与注记,map.getStyle().layers.length 大于 0。 控制台不再出现 style is not done loading。

别忽略 sprite:样式主体正常但图标、箭头全缺失,多半是 sprite 指向的资源 404。style.json 里只写前缀,不带 .json 与 .png, MapLibre 会自己拼出三个文件。

引用本文

经纬志(2026)。《样式加载失败,地图一直是灰底》。https://www.jingweizhi.com/cookbook/maplibre-style-load-fail.html(访问日期 2026-11-03)。