Skip to content

入门 ​

两个最简单的出图方式:直接使用矢量瓦片服务的样式,或直接使用地图方案的样式地址。示例代码里的 client、container、services、maps 由沙箱提供,拷到自己页面时的替换方法见示例总览。

矢量瓦片服务样式 ​

用 client.maplibre.serviceStyle() 取矢量瓦片服务的样式 JSON,直接作为 MapLibre 地图的样式;transformRequest 负责给发往平台的请求带上 Key。样式里的数据源、字体与图标地址都指向平台,不需要再做其他配置。左上角在每次地图静止后统计视野内渲染出的道路段数。示例视野放在尖沙咀、15 级附近,可以缩小查看:瓦片包含范围内的全部道路,小于约一个像素的短路段在低级别不输出;道路数据量大,10 级以下的瓦片中没有道路(tiles.json 中图层的 minzoom 即为 10)。

需要: 一个矢量瓦片服务(示例用香港道路;公开服务匿名即可访问,受保护服务需在沙箱顶部填写 API Key)。

js
/**
 * @title 矢量瓦片服务样式
 * @description 取香港道路矢量瓦片服务的样式 JSON,直接作为 MapLibre 地图的样式;左上角实时统计视野内的道路段数,缩放平移后自动更新。
 * @category 入门
 * @service demo/roads
 */
// 出错时给出可理解的提示(服务不存在多半是 demo 服务映射或服务路径有误)
const friendly = (e) => (e && e.status === 404 ? '服务不存在,请检查服务路径' : e && e.message)

try {
  // 拷到自己页面时:把 services['demo/roads'] 换成你的矢量瓦片服务路径
  const path = services['demo/roads']

  // serviceStyle 取回的样式里 source、glyphs 与 sprite 都指向平台,可直接交给地图
  const style = await client.maplibre.serviceStyle(path)

  const map = new maplibregl.Map({
    container,
    style,
    // 给发往平台的请求带上 Key(匿名访问公开服务时什么也不加)
    transformRequest: client.transformRequest,
    // 尖沙咀一带。道路数据量大:这个服务在 10 级以下不出瓦片(tiles.json 的 minzoom),低级别不输出小于约一个像素的短路段
    center: [114.172, 22.298],
    zoom: 15.5,
  })
  map.addControl(new maplibregl.NavigationControl())
  // 切片、图标等资源加载失败时 MapLibre 发 error 事件:转成提示,不影响其余内容显示
  map.on('error', (e) => console.warn('地图资源加载失败:', e.error && e.error.message))

  // 视野统计面板:每次地图静止(idle)后,数一数当前渲染出来的道路要素
  const panel = document.createElement('div')
  panel.style.cssText = 'position:absolute;top:8px;left:8px;z-index:2;background:#fff;padding:6px 10px;border-radius:6px;box-shadow:0 1px 4px rgba(0,0,0,.3);font:13px/1.6 sans-serif'
  container.appendChild(panel)

  const layerIds = style.layers.map((l) => l.id)
  let logged = false
  map.on('idle', () => {
    const features = map.queryRenderedFeatures({ layers: layerIds })
    const named = features.filter((f) => f.properties.name).length
    panel.textContent = `缩放 ${map.getZoom().toFixed(1)}:视野内道路 ${features.length} 段,其中有名称 ${named} 段`
    if (!logged) {
      logged = true
      console.log('样式图层:', layerIds.join('、'), ';', panel.textContent)
    }
  })
} catch (e) {
  console.error(friendly(e))
}
在沙箱中打开

地图方案样式 ​

在地图编辑器里制作并发布的地图方案有一个公开的样式地址(client.maplibre.mapStyleUrl()),直接交给 style 即可;方案里引用的服务请求仍然通过 transformRequest 带 Key。地图加载后,示例按数据源把方案的图层分组,左上角的复选框可以分别开关土地利用、水体、建筑、道路与兴趣点。

需要: 一个已发布、可公开访问的地图方案。

js
/**
 * @title 地图方案样式
 * @description 把地图方案公开的样式地址直接交给 style,得到在地图编辑器里配好的香港底图;右上角的复选框按数据源开关方案里的图层。
 * @category 入门
 * @map demo/map
 */
// 出错时给出可理解的提示(地图方案不存在多半是 demo 映射或方案 id 有误)
const friendly = (e) => (e && e.status === 404 ? '地图方案不存在,请检查方案 id' : e && e.message)

try {
  // 拷到自己页面时:把 maps['demo/map'] 换成你的地图方案 id(方案须已发布并公开)
  const mapId = maps['demo/map']

  const map = new maplibregl.Map({
    container,
    style: client.maplibre.mapStyleUrl(mapId),
    // 方案引用的服务请求仍经 transformRequest 带 Key
    transformRequest: client.transformRequest,
    // 尖沙咀一带,放大到能看清建筑与兴趣点
    center: [114.172, 22.298],
    zoom: 15.5,
  })
  map.addControl(new maplibregl.NavigationControl())
  map.on('error', (e) => console.error('地图出错:', e.error && e.error.message))
  await new Promise((resolve) => map.once('load', resolve))

  // 方案的图层按 source 分组:同一个数据源(服务)下的图层一起开关
  const groups = {}
  for (const layer of map.getStyle().layers) {
    if (!layer.source) continue
    groups[layer.source] = [...(groups[layer.source] || []), layer.id]
  }

  const panel = document.createElement('div')
  panel.style.cssText = 'position:absolute;top:8px;left:8px;z-index:2;background:#fff;padding:6px 10px;border-radius:6px;box-shadow:0 1px 4px rgba(0,0,0,.3);font:13px/1.8 sans-serif'
  for (const [source, ids] of Object.entries(groups)) {
    const label = document.createElement('label')
    label.style.display = 'block'
    const box = document.createElement('input')
    box.type = 'checkbox'
    box.checked = true
    // setLayoutProperty 改 visibility 只影响显示,不会重新请求样式
    box.onchange = () => ids.forEach((id) => map.setLayoutProperty(id, 'visibility', box.checked ? 'visible' : 'none'))
    label.append(box, ` ${source}(${ids.length} 个图层)`)
    panel.appendChild(label)
  }
  container.appendChild(panel)

  console.log('地图方案加载完成:', Object.entries(groups).map(([s, ids]) => `${s} ${ids.length} 层`).join(','))
} catch (e) {
  console.error(friendly(e))
}
在沙箱中打开