You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Supabase RPC生成MVT矢量瓦片在MapLibre中无法显示的问题

排查Supabase RPC生成MVT在MapLibre中无法显示的问题

以下是从RPC函数、前端协议处理到MapLibre配置的逐项排查及修复方案:

一、Supabase RPC函数问题

1. 空瓦片场景下返回值为null

当瓦片范围内没有匹配的几何数据时,ST_AsMVT会返回空,后续的encode操作会得到null,最终函数返回null。前端处理null的base64字符串会直接报错。

修复方案:使用COALESCE确保即使没有数据也返回空的base64编码MVT,同时调整查询数据源保证始终返回一行结果:

CREATE OR REPLACE FUNCTION mvt(z integer, x integer, y integer)
RETURNS text
LANGUAGE plpgsql
AS $$
DECLARE
    mvt_output text;
BEGIN
    WITH
    bounds AS (
        SELECT ST_TileEnvelope(z, x, y) AS geom
    ),
    mvtgeom AS (
        SELECT
            ST_AsMVTGeom(
                ST_Transform(geometry, 3857),
                bounds.geom,
                4096,
                0,
                true
            ) AS geom
        FROM
            property_geodata, bounds
        WHERE
            ST_Intersects(ST_Transform(geometry, 3857), bounds.geom)
    )
    SELECT INTO mvt_output 
           COALESCE(encode(ST_AsMVT(mvtgeom, 'property_geodata', 4096, 'geom'),'base64'), '')
    FROM bounds;

    RETURN mvt_output;
END;
$$;

2. 聚合查询数据源错误

原代码中FROM mvtgeom会在无匹配数据时返回0行,导致mvt_output未赋值。改为从bounds查询(bounds始终有一行数据),确保SELECT INTO总能拿到值。

二、前端自定义协议处理问题

1. 字符串参数未转为整数

RPC函数要求z/x/y为整数类型,但正则匹配得到的是字符串,直接传递会导致类型不兼容,触发函数执行错误。

修复方案:将匹配结果转为整数:

const { data, error } = await client.rpc("mvt", {
  z: parseInt(result[2], 10),
  x: parseInt(result[3], 10),
  y: parseInt(result[4], 10),
});

2. 空数据与错误处理缺失

当RPC返回空字符串或null时,atob会报错;错误信息未完整抛出,无法排查问题。

修复方案:添加空值判断与完整错误信息:

maplibregl.addProtocol("supabase", async (params, abortController) => {
  const re = new RegExp(/supabase:\/\/(.+)\/(\d+)\/(\d+)\/(\d+)/);
  const result = params.url.match(re);
  if (!result) throw new Error("Invalid tile URL format");

  const { data, error } = await client.rpc("mvt", {
    z: parseInt(result[2], 10),
    x: parseInt(result[3], 10),
    y: parseInt(result[4], 10),
  });

  if (error) {
    throw new Error(`Tile fetch error: ${error.message}`);
  }

  // 处理空数据
  if (!data) {
    return { data: new Uint8Array() };
  }

  const encoded = base64ToArrayBuffer(data);
  return { data: encoded };
});

三、MapLibre配置问题

1. 瓦片尺寸不匹配

ST_TileEnvelope默认生成256像素的瓦片,而MapLibre矢量数据源默认tileSize为512,会导致瓦片对齐错误,无法正确渲染。

修复方案:在自定义数据源中指定tileSize: 256:

"custom-tiles": {
  type: "vector",
  tiles: ["supabase://mvt/{z}/{x}/{y}"],
  minzoom: 2,
  maxzoom: 15,
  tileSize: 256 // 添加此行
},

2. 点击事件图层ID不匹配

点击事件中查询的polygon-layer与实际图层IDpolygon-outline不一致,导致无法捕获点击事件(虽不影响瓦片显示,但属于逻辑错误):

const features = map.queryRenderedFeatures(e.point, {
  layers: ["polygon-outline"], // 改为实际图层ID
});

内容的提问来源于stack exchange,提问作者Nuwe Ariho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 09:36:15