mahal_map 1.6.21 → 1.6.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -12,10 +12,10 @@ npm install mahal_map maplibre-gl
12
12
 
13
13
  `maplibre-gl` является peer dependency. Его нужно установить в приложении или подключить отдельным browser script перед SDK.
14
14
 
15
- Для нового 3D-движка (`engine: "3d"`) дополнительно нужен `@grammaps/maps3d-web`:
15
+ `@grammaps/maps3d-web` объявлен peer dependency пакета (в `package.json` помечен как `optional` — без него `engine: "legacy"` работает как обычно). Для `engine: "3d"` он обязателен в рантайме: установите его явно.
16
16
 
17
17
  ```sh
18
- npm i @grammaps/maps3d-web maplibre-gl
18
+ npm i mahal_map maplibre-gl @grammaps/maps3d-web
19
19
  ```
20
20
 
21
21
  ## Быстрый старт через NPM
@@ -71,8 +71,6 @@ const map = MahalMap.create(
71
71
  </script>
72
72
  ```
73
73
 
74
- ````
75
-
76
74
  Через NPM язык можно передать при создании карты:
77
75
 
78
76
  ```ts
@@ -84,7 +82,7 @@ const map = MahalMap.create(
84
82
  },
85
83
  maplibregl,
86
84
  );
87
- ````
85
+ ```
88
86
 
89
87
  Через browser SDK язык можно передать в URL скрипта:
90
88
 
@@ -96,9 +94,13 @@ const map = MahalMap.create(
96
94
 
97
95
  ## Параметры создания карты
98
96
 
99
- `MahalMap.create(options, maplibreObject?)`
97
+ `MahalMap.create(options, maplibreObject?, maps3dCtor?)`
98
+
99
+ `maps3dCtor` — импортированный конструктор `Maps3D` (третий, необязательный аргумент). Если не передан, SDK ищет его в `window.Maps3D`.
100
100
 
101
101
  ```ts
102
+ import type { IMaps3DLayerOptions } from "mahal_map";
103
+
102
104
  interface IMahalMapOptions {
103
105
  container?: string | HTMLElement;
104
106
  style?: string;
@@ -113,7 +115,7 @@ interface IMahalMapOptions {
113
115
  enable3D?: boolean;
114
116
  base?: string;
115
117
  preset?: string;
116
- maps3d?: IMaps3DOptions;
118
+ maps3d?: Omit<IMaps3DLayerOptions, "apiKey" | "base" | "buildings">;
117
119
  }
118
120
  ```
119
121
 
@@ -190,14 +192,26 @@ MahalMap.getMaps3DLayer(map);
190
192
 
191
193
  ### 3D-здания
192
194
 
193
- `Maps3D` рисует процедурные 3D-здания (three.js) вместо плоской `fill-extrusion` стиля: фаска кромок, вертикальный градиент и базовый цвет берутся из стиля, окна — из `metadata` пресета. При `engine: "3d"` слой создаётся и `attach`-ится к карте автоматически (`enable3D` по умолчанию `true`) — вручную поднимать `new Maps3D(...)` не нужно, только если требуется отдельный кастомный инстанс:
195
+ `Maps3D` рисует процедурные 3D-здания (three.js) вместо плоской `fill-extrusion` стиля: фаска кромок, вертикальный градиент и базовый цвет берутся из стиля, окна — из `metadata` пресета. При `engine: "3d"` слой создаётся и `attach`-ится к карте автоматически (`enable3D` по умолчанию `true`) — вручную поднимать `new Maps3D(...)` не нужно, только если требуется отдельный кастомный инстанс.
196
+
197
+ **Ручной `new Maps3D(...)` — отдельный сценарий.** Карту при этом создавайте с `enable3D: false`, иначе на неё повиснут два слоя Maps3D сразу (автоматический от `MahalMap` + ваш ручной) — дублирование зданий и лишний расход ресурсов:
194
198
 
195
199
  ```ts
200
+ const apiKey = "YOUR_MAP_API_KEY";
201
+ const base = "https://navi.gram.tj";
202
+
203
+ const map = MahalMap.create(
204
+ { container: "map", engine: "3d", enable3D: false },
205
+ maplibregl,
206
+ );
207
+
196
208
  const layer = new Maps3D({ apiKey, base, buildings: true });
197
- await layer.attach(map); // attach асинхронный, дожидается load карты сам
209
+ await layer.attach(map.getMap()); // attach ждёт нативную карту MapLibre, не обёртку MahalMap
198
210
  ```
199
211
 
200
- Тема (окна/свет) приходит из `metadata` пресета стиля и применяется автоматически при `map.setStyle()` — пересоздавать слой не нужно. Ручные сеттеры перебивают её:
212
+ Тема (окна/свет) приходит из `metadata` пресета стиля и применяется автоматически при `map.setStyle()` — пересоздавать слой не нужно. Ручные сеттеры перебивают её.
213
+
214
+ Это работает только для встроенных пресетов **без** явного `options.preset`: `setStyle()` меняет пресет по теме (`light`/`dark` → `GRAM_PRESETS`), а при заданном `preset` считает стиль зафиксированным и ничего не делает (см. [`MahalMap.ts`](src/core/MahalMap.ts:363)). Чтобы сменить пресет/тему в этом случае — пересоздайте карту с другим `preset` или вызовите `map.getMap().setStyle(...)` напрямую.
201
215
 
202
216
  ```ts
203
217
  const layer = map.getMaps3DLayer();
@@ -222,13 +236,7 @@ layer?.onBuildingClick((info) => {
222
236
 
223
237
  #### Вкл/выкл 3D-здания на лету
224
238
 
225
- Переключение 3D-здания ⇄ штатные здания стиля, без пересоздания карты:
226
-
227
- ```ts
228
- layer?.setBuildingsEnabled(false); // напрямую через слой
229
- ```
230
-
231
- Либо через обёртку `MahalMap` — она же умеет пересоздать слой, если его не было (`enable3D: false` при создании):
239
+ Переключение 3D-здания ⇄ штатные здания стиля, без пересоздания карты — через обёртку `MahalMap`. Она же умеет пересоздать слой, если его не было (`enable3D: false` при создании):
232
240
 
233
241
  ```ts
234
242
  const map = MahalMap.getInstance("map");
@@ -240,6 +248,182 @@ map.toggle3DBuildings(true); // вкл обратно
240
248
  MahalMap.toggle3DBuildings(map, false);
241
249
  ```
242
250
 
251
+ `layer?.setBuildingsEnabled(false)` напрямую через слой **не используйте** — он не знает про штатный слой стиля `building-3d`, который `MahalMap` прячет при включённом 3D. Вызов только слоя оставит эти штатные здания скрытыми и одновременно выключит процедурные — в итоге зданий не будет видно вообще, до следующей перезагрузки стиля.
252
+
253
+ #### `map.whenMaps3DReady()`
254
+
255
+ `attach()` слоя асинхронный: сразу после `create()` слой уже есть, но `layer.buildings` (окна, свет, кромки) появляется только после attach. Чтобы не гадать — дождитесь готовности:
256
+
257
+ ```ts
258
+ const layer = await map.whenMaps3DReady();
259
+
260
+ layer?.buildings?.setWindowStyle(4);
261
+ ```
262
+
263
+ Промис резолвится в `undefined`, если движок не `"3d"`, слой выключен (`enable3D: false`) или attach упал — ошибка при этом уходит в `console.error`, а карта остаётся живой со штатными зданиями стиля.
264
+
265
+ ### Подключение и выключение 3D-слоя: полный пример (Vue 3)
266
+
267
+ Кнопка-переключатель «3D ⇄ контуры», тонкая настройка окон и корректная очистка при размонтировании. Слой `Maps3D` поднимает и цепляет сама библиотека — вручную `new Maps3D(...)`, `transformRequest` и `attach()` писать не нужно.
268
+
269
+ ```vue
270
+ <script setup lang="ts">
271
+ import { computed, onBeforeUnmount, onMounted, ref, shallowRef } from "vue";
272
+ import maplibregl from "maplibre-gl";
273
+ import "maplibre-gl/dist/maplibre-gl.css";
274
+ import { Maps3D } from "@grammaps/maps3d-web";
275
+ import { MahalMap, keyUtils } from "mahal_map";
276
+
277
+ const API_KEY = "YOUR_MAP_API_KEY";
278
+
279
+ const mahalMap = shallowRef<MahalMap | null>(null);
280
+ const is3dEnabled = ref(true);
281
+ const isLayerReady = ref(false);
282
+
283
+ const buildingModeText = computed(() =>
284
+ is3dEnabled.value ? "3D включено" : "Контуры",
285
+ );
286
+ const buildingToggleText = computed(() =>
287
+ is3dEnabled.value ? "Выключить 3D" : "Включить 3D",
288
+ );
289
+
290
+ function toggle3dBuildings() {
291
+ is3dEnabled.value = !is3dEnabled.value;
292
+ // Вкл/выкл детальных 3D-зданий: библиотека сама вернёт/спрячет плоские здания стиля.
293
+ mahalMap.value?.toggle3DBuildings(is3dEnabled.value);
294
+ }
295
+
296
+ onMounted(async () => {
297
+ // Токен — один на всё (стиль, тайлы, Maps3D). Отдельный apiKey слою передавать не нужно.
298
+ keyUtils.saveKey(API_KEY);
299
+
300
+ const map = MahalMap.create(
301
+ {
302
+ container: "map",
303
+ engine: "3d", // платформа GramMaps вместо legacy-стилей
304
+ theme: "dark", // preset standard-night; "light" → road-urban-lab-v2
305
+ center: [68.787, 38.573],
306
+ zoom: 16.6,
307
+ pitch: 58, // без наклона экструзия не видна
308
+ bearing: -20,
309
+ enable3D: true, // значение по умолчанию для engine: "3d"
310
+ maps3d: { minZoom: 16, lodBias: 0 },
311
+ },
312
+ maplibregl,
313
+ Maps3D,
314
+ );
315
+
316
+ mahalMap.value = map;
317
+
318
+ // Дожидаемся attach(): до него layer.buildings ещё нет.
319
+ const layer = await map.whenMaps3DReady();
320
+ const buildings = layer?.buildings;
321
+
322
+ if (!buildings) {
323
+ return;
324
+ }
325
+
326
+ buildings.setWindowMinZoom?.(16);
327
+ buildings.setWindowStyle(4);
328
+ buildings.setWindowDepth(0.85);
329
+ buildings.setWindowColor("#6b9ed1");
330
+ buildings.setWindowFrameColor("#f2f2f4");
331
+ buildings.setWindowGlow?.(0.22);
332
+ buildings.setEdgeRadius(1.2);
333
+
334
+ isLayerReady.value = true;
335
+ });
336
+
337
+ onBeforeUnmount(() => {
338
+ isLayerReady.value = false;
339
+ // destroy() сам снимает слой Maps3D и удаляет карту MapLibre.
340
+ mahalMap.value?.destroy();
341
+ mahalMap.value = null;
342
+ });
343
+ </script>
344
+
345
+ <template>
346
+ <main class="map-page">
347
+ <div id="map" class="map" />
348
+
349
+ <section class="panel" aria-label="GramMaps 3D">
350
+ <span class="mode-label">{{ buildingModeText }}</span>
351
+ <button
352
+ type="button"
353
+ :aria-pressed="is3dEnabled"
354
+ :disabled="!isLayerReady"
355
+ @click="toggle3dBuildings"
356
+ >
357
+ {{ buildingToggleText }}
358
+ </button>
359
+ </section>
360
+ </main>
361
+ </template>
362
+
363
+ <style>
364
+ .map-page,
365
+ .map {
366
+ position: absolute;
367
+ inset: 0;
368
+ }
369
+
370
+ .panel {
371
+ position: absolute;
372
+ top: 12px;
373
+ left: 12px;
374
+ z-index: 2;
375
+ }
376
+ </style>
377
+ ```
378
+
379
+ Что библиотека делает за вас против ручного подключения `@grammaps/maps3d-web`:
380
+
381
+ | Ручной код | Через `mahal_map` |
382
+ | ----------------------------------------------- | ----------------------------------------------------------------- |
383
+ | `style: base + "/maps/standard-night.json"` | `engine: "3d"` + `theme` (или `preset` / `base` явно) |
384
+ | `transformRequest: Maps3D.transformRequest(..)` | ставится автоматически (и без Maps3D — своим фолбэком с `?key=`) |
385
+ | `new Maps3D({...}); await layer.attach(map)` | `enable3D: true` + `maps3d: {...}`, `await map.whenMaps3DReady()` |
386
+ | `setBuildingsEnabled` + `buildings.setWindows` | `map.toggle3DBuildings(enabled)` — оба вызова разом |
387
+ | Плоские здания стиля поверх 3D после `setStyle` | скрываются сами на каждой загрузке стиля |
388
+ | `layer.destroy(); map.remove()` | `map.destroy()` |
389
+
390
+ #### То же самое без сборщика (browser SDK)
391
+
392
+ ```html
393
+ <script src="https://unpkg.com/maplibre-gl@5.3.0/dist/maplibre-gl.js"></script>
394
+ <script src="https://cdn.jsdelivr.net/npm/@grammaps/maps3d-web/dist/maps3d.global.js"></script>
395
+ <script src="https://cp.mahal.tj/sdk/mahal_map.sdk.js?apikey=YOUR_MAP_API_KEY"></script>
396
+
397
+ <div id="map" style="width: 100%; height: 500px"></div>
398
+ <button id="toggle3d" type="button">Выключить 3D</button>
399
+
400
+ <script>
401
+ // Maps3D берётся из window.Maps3D — третий аргумент передавать не нужно.
402
+ const map = MahalMap.create({
403
+ container: "map",
404
+ engine: "3d",
405
+ theme: "dark",
406
+ center: [68.787, 38.573],
407
+ zoom: 16.6,
408
+ pitch: 58,
409
+ });
410
+
411
+ let enabled = true;
412
+
413
+ document.getElementById("toggle3d").addEventListener("click", () => {
414
+ enabled = !enabled;
415
+ MahalMap.toggle3DBuildings(map, enabled);
416
+ document.getElementById("toggle3d").textContent = enabled
417
+ ? "Выключить 3D"
418
+ : "Включить 3D";
419
+ });
420
+
421
+ MahalMap.whenMaps3DReady(map).then((layer) => {
422
+ layer?.buildings?.setWindowStyle(4);
423
+ });
424
+ </script>
425
+ ```
426
+
243
427
  ### Пробки
244
428
 
245
429
  ```ts
@@ -263,18 +447,17 @@ layer?.setMinZoom(15);
263
447
  layer?.setObjectsLight({ sun: 1.8, ambient: 0.45, sky: 1.1, exposure: 1.15 });
264
448
  await layer?.refresh(); // перечитать модели после правок
265
449
  await layer?.clearCache(); // сбросить IndexedDB-кеш ассетов
266
- layer?.destroy?.(); // отцепить слой (также вызывается автоматически в map.destroy())
267
450
  ```
268
451
 
269
- `map.destroy()` / `MahalMap.destroy(map)` сами вызывают `destroy()`/`remove()` у Maps3D слоя, если он был подключенотдельно чистить не нужно.
452
+ Для полной остановки карты используйте только `map.destroy()` / `MahalMap.destroy(map)` — они сами вызывают `destroy()`/`remove()` у Maps3D слоя. **Не вызывайте `layer.destroy()`/`layer.remove()` напрямую**: `MahalMap` не узнает об этом и продолжит считать слой активным (внутренний `maps3dLayer`, `buildingsEnabled`, видимость штатных зданий стиля разойдутся с реальностью). Нужно временно выключить только 3D-здания используйте `map.toggle3DBuildings(false)` (см. выше).
270
453
 
271
454
  ## MahalMap
272
455
 
273
456
  `MahalMap` - основной класс карты. Конструктор закрыт, карту нужно создавать через `MahalMap.create()`.
274
457
 
275
- ### `MahalMap.create(options, maplibreObject?)`
458
+ ### `MahalMap.create(options, maplibreObject?, maps3dCtor?)`
276
459
 
277
- Создает новый инстанс карты и сохраняет его по ключу `container`. Для стандартных стилей перед созданием карты должен быть сохранен map token через `keyUtils.saveKey()`. В browser SDK token читается из обязательного URL-параметра `apikey`.
460
+ Создает новый инстанс карты и сохраняет его по ключу `container`. Для стандартных стилей перед созданием карты должен быть сохранен map token через `keyUtils.saveKey()`. В browser SDK token читается из обязательного URL-параметра `apikey`. Третий аргумент — необязательный конструктор `Maps3D`; без него SDK использует `window.Maps3D`.
278
461
 
279
462
  ```ts
280
463
  const map = MahalMap.create(
@@ -472,6 +655,7 @@ MahalMap.setCenter(map, [69.624024, 40.279687]);
472
655
  MahalMap.setZoom(map, 14);
473
656
  MahalMap.addMarker(map, marker);
474
657
  MahalMap.getMaps3DLayer(map);
658
+ MahalMap.whenMaps3DReady(map);
475
659
  MahalMap.toggle3DBuildings(map, false);
476
660
  MahalMap.destroy(map);
477
661
  ```
@@ -511,6 +695,7 @@ MahalMap.setZoom(map, 14);
511
695
  | `setZoom(instance, zoom)` | Меняет zoom карты. |
512
696
  | `addMarker(instance, marker)` | Добавляет маркер. |
513
697
  | `getMaps3DLayer(instance)` | Возвращает инстанс слоя Maps3D (только `engine: "3d"`). |
698
+ | `whenMaps3DReady(instance)` | Промис слоя Maps3D после `attach()` (готов `layer.buildings`). |
514
699
  | `toggle3DBuildings(instance, enabled)` | Вкл/выкл детальные 3D-здания на лету (только `engine: "3d"`). |
515
700
  | `destroy(instance)` | Полностью удаляет карту. |
516
701
  | `loadKeyFromScriptUrl()` | Читает `apikey` из URL SDK скрипта. |
package/dist/index.d.mts CHANGED
@@ -216,6 +216,7 @@ type MapLibreApi = {
216
216
  declare class MahalMap {
217
217
  private static instances;
218
218
  private static defaultLanguage;
219
+ private static disposedMaps3DLayers;
219
220
  private isReady;
220
221
  private readyCallbacks;
221
222
  private map;
@@ -233,8 +234,7 @@ declare class MahalMap {
233
234
  private presetIsExplicit;
234
235
  private maps3dCtor?;
235
236
  private maps3dLayer?;
236
- private maps3dLayerReady;
237
- private maps3dLayerAttachPending;
237
+ private maps3dReady?;
238
238
  private buildingsEnabled;
239
239
  private constructor();
240
240
  private static getInstanceKey;
@@ -254,6 +254,7 @@ declare class MahalMap {
254
254
  static getMap(instance: MahalMap): Map;
255
255
  static setStyle(instance: MahalMap, theme: Theme): void;
256
256
  static getMaps3DLayer(instance: MahalMap): IMaps3DLayer | undefined;
257
+ static whenMaps3DReady(instance: MahalMap): Promise<IMaps3DLayer | undefined>;
257
258
  static toggle3DBuildings(instance: MahalMap, enabled: boolean): void;
258
259
  static setLanguage(instance: MahalMap, lang: MapLanguage): void;
259
260
  static setCenter(instance: MahalMap, center: [number, number]): void;
@@ -268,12 +269,29 @@ declare class MahalMap {
268
269
  getMaps3DLayer(): IMaps3DLayer | undefined;
269
270
  /** Вкл/выкл детальные 3D-здания (Maps3D). Работает только для engine: "3d". */
270
271
  toggle3DBuildings(enabled: boolean): void;
272
+ /**
273
+ * Промис готовности слоя Maps3D: резолвится после attach(), когда доступен layer.buildings.
274
+ * Нужен для тонкой настройки окон/света — до attach контроллера зданий ещё нет.
275
+ * Резолвится в undefined, если движок не "3d", слой выключен или attach упал.
276
+ */
277
+ whenMaps3DReady(): Promise<IMaps3DLayer | undefined>;
271
278
  private attachMaps3DLayer;
279
+ /**
280
+ * Освобождает слой Maps3D одним доступным методом (destroy(), иначе remove()) и ровно один
281
+ * раз: destroy()/attach-catch/toggle3DBuildings(false) все могут метить в один и тот же layer
282
+ * (напр. map.destroy() случился, пока attach() ещё не резолвился) — без WeakSet-гварда второй
283
+ * вызов teardown попал бы на уже освобождённый объект.
284
+ */
285
+ private static teardownMaps3DLayer;
272
286
  private applyMaps3DBuildingMode;
273
287
  /**
274
- * Прячет/показывает нативные здания стиля GramMaps ("building-3d" и любые fill-extrusion /
275
- * fill+source-layer=building), не задевая слои самого Maps3D. Нужно, иначе плоский слой стиля
276
- * рисуется поверх процедурных 3D-зданий и визуально их перекрывает.
288
+ * Прячет/показывает нативный слой зданий GramMaps-пресетов ("building-3d"), не задевая слои
289
+ * самого Maps3D. Нужно, иначе плоский слой стиля рисуется поверх процедурных 3D-зданий и
290
+ * визуально их перекрывает.
291
+ *
292
+ * Только для встроенных пресетов (buildGramStyleUrl) — при пользовательском `options.style`
293
+ * мы не знаем структуру стиля, гасить слои по имени/source-layer небезопасно (можно случайно
294
+ * погасить чужую fill-extrusion, никак не связанную со зданиями GramMaps).
277
295
  */
278
296
  private setNativeBuildingsVisible;
279
297
  setCenter(center: [number, number]): void;
package/dist/index.d.ts CHANGED
@@ -216,6 +216,7 @@ type MapLibreApi = {
216
216
  declare class MahalMap {
217
217
  private static instances;
218
218
  private static defaultLanguage;
219
+ private static disposedMaps3DLayers;
219
220
  private isReady;
220
221
  private readyCallbacks;
221
222
  private map;
@@ -233,8 +234,7 @@ declare class MahalMap {
233
234
  private presetIsExplicit;
234
235
  private maps3dCtor?;
235
236
  private maps3dLayer?;
236
- private maps3dLayerReady;
237
- private maps3dLayerAttachPending;
237
+ private maps3dReady?;
238
238
  private buildingsEnabled;
239
239
  private constructor();
240
240
  private static getInstanceKey;
@@ -254,6 +254,7 @@ declare class MahalMap {
254
254
  static getMap(instance: MahalMap): Map;
255
255
  static setStyle(instance: MahalMap, theme: Theme): void;
256
256
  static getMaps3DLayer(instance: MahalMap): IMaps3DLayer | undefined;
257
+ static whenMaps3DReady(instance: MahalMap): Promise<IMaps3DLayer | undefined>;
257
258
  static toggle3DBuildings(instance: MahalMap, enabled: boolean): void;
258
259
  static setLanguage(instance: MahalMap, lang: MapLanguage): void;
259
260
  static setCenter(instance: MahalMap, center: [number, number]): void;
@@ -268,12 +269,29 @@ declare class MahalMap {
268
269
  getMaps3DLayer(): IMaps3DLayer | undefined;
269
270
  /** Вкл/выкл детальные 3D-здания (Maps3D). Работает только для engine: "3d". */
270
271
  toggle3DBuildings(enabled: boolean): void;
272
+ /**
273
+ * Промис готовности слоя Maps3D: резолвится после attach(), когда доступен layer.buildings.
274
+ * Нужен для тонкой настройки окон/света — до attach контроллера зданий ещё нет.
275
+ * Резолвится в undefined, если движок не "3d", слой выключен или attach упал.
276
+ */
277
+ whenMaps3DReady(): Promise<IMaps3DLayer | undefined>;
271
278
  private attachMaps3DLayer;
279
+ /**
280
+ * Освобождает слой Maps3D одним доступным методом (destroy(), иначе remove()) и ровно один
281
+ * раз: destroy()/attach-catch/toggle3DBuildings(false) все могут метить в один и тот же layer
282
+ * (напр. map.destroy() случился, пока attach() ещё не резолвился) — без WeakSet-гварда второй
283
+ * вызов teardown попал бы на уже освобождённый объект.
284
+ */
285
+ private static teardownMaps3DLayer;
272
286
  private applyMaps3DBuildingMode;
273
287
  /**
274
- * Прячет/показывает нативные здания стиля GramMaps ("building-3d" и любые fill-extrusion /
275
- * fill+source-layer=building), не задевая слои самого Maps3D. Нужно, иначе плоский слой стиля
276
- * рисуется поверх процедурных 3D-зданий и визуально их перекрывает.
288
+ * Прячет/показывает нативный слой зданий GramMaps-пресетов ("building-3d"), не задевая слои
289
+ * самого Maps3D. Нужно, иначе плоский слой стиля рисуется поверх процедурных 3D-зданий и
290
+ * визуально их перекрывает.
291
+ *
292
+ * Только для встроенных пресетов (buildGramStyleUrl) — при пользовательском `options.style`
293
+ * мы не знаем структуру стиля, гасить слои по имени/source-layer небезопасно (можно случайно
294
+ * погасить чужую fill-extrusion, никак не связанную со зданиями GramMaps).
277
295
  */
278
296
  private setNativeBuildingsVisible;
279
297
  setCenter(center: [number, number]): void;