zoom-level-map
本文回答:CAD 图 zoom 与互联网地图 zoom 怎么对齐,避免放大后互联网底图消失。
一、问题
CAD 图用 GeoProjection(mapExtent) 初始化时,zoom=2 可能等于互联网地图的 zoom=N 的某个值;不同图随范围而异。
如果 CAD 全图显示对应的 zoom 太大(例如 20),往外缩一点就"越界"了,看不到互联网瓦片。
二、设置初始 zoom + clipbounds
const initZoom = 8; // 期望全图 = 互联网地图 8 级
const style = {
backcolor: 0,
clipbounds: Math.pow(2, initZoom) // 只传值,意味着把 bounds 放大 2^initZoom
};
const res = await svc.openMap({ mapid, mapopenway: vjmap.MapOpenWay.GeomRender, style });
const mapExtent = vjmap.GeoBounds.fromString(res.bounds);
const prj = new vjmap.GeoProjection(mapExtent);
const map = new vjmap.Map({
container: "map",
style: svc.rasterStyle(),
center: prj.toLngLat(mapExtent.center()),
zoom: initZoom, // 与 clipbounds 匹配
renderWorldCopies: false
});
map.attach(svc, prj);
三、原理
- CAD 的
bounds实际占用的 Mercator 范围在某个 zoom 下被切成 1 个 tile。 - 我们把 CAD bounds 扩大 2^initZoom 倍,等价于 CAD 在 initZoom 级别时对应屏幕 1 个 tile;缩小 initZoom 级就是全世界 1 个 tile。
- 这样 CAD 地图 zoom 变量和互联网地图一致,缩小到 zoom=2 仍然有瓦片可取。
四、不同图范围的估算
function recommendZoom(bounds) {
const lon = bounds.width();
// Mercator 大概 4.0 × 10^7 = 全世界;目标:CAD 全图 ≈ 世界的 1/2^zoom
const world = 4e7;
return Math.max(2, Math.round(Math.log2(world / lon)));
}
五、互联网为底图时的常见 zoom
zoom=3 全国大致
zoom=5 省级
zoom=8 地级市(推荐 CAD 为底图时的默认 initZoom)
zoom=12 区县
zoom=15 街道
zoom=18 大楼/小区
六、互联网瓦片的 zoom 上限
| 厂商 | maxZoom |
|---|---|
| 天地图 | 18 |
| 高德 | 18 |
| 百度 | 19 |
| OSM | 19 |
| 国际矢量底图 | 22 |
| 22 |
CAD 图放大到 zoom > maxZoom 时互联网瓦片会 "过缩放"(overzoom)模糊;可以 maxzoom: 18 + source.maxzoom: 18。
七、tileSize 必须写真实瓦片尺寸
引擎取瓦片级别 = round(zoom + log2(512 / tileSize)),与 devicePixelRatio 无关(retina 不会让"有效 zoom" +1)。tileSize 必须等于服务实际瓦片像素:256 瓦片写 256(地图 zoom z 取 z+1 级瓦片);把 256 瓦片谎报成 512 会取低一级瓦片放大,画面发糊。
map.addSource("osm", {
type: "raster",
tileSize: 256, // OSM 是 256 瓦片
tiles: [...]
});
八、常见坑
- CAD 为底图但
zoom=2时互联网瓦片空白 →clipbounds没设置或 initZoom 太小。按前面的 initZoom=8 试。 fitMapBounds后 CAD 图只占半屏:因为clipbounds放大后地图范围远大于 CAD,fitMapBounds 贴了放大的边。可以改 fitMapBounds 传 CAD 实际 bounds。- 互联网瓦片远处"横条黑边" →
renderWorldCopies: true时会重复地图;互联网地图通常false。