PageSourceSearch

https://proparcel.com/static/js/core/map/map_manager_core_v3.js?v=20260810-mode-overlay

js proparcel.com collected 2026-09-24 14:51:25 UTC 15,922 bytes, 412 lines download raw bytes

1(function () {
2  if (!window.MapManagerCore) {
3    window.MapManagerCore = {};
4  }
5
6  // --- YARDIMCI FONKSİYONLAR ---
7
8  function createBaseStyle(manager) {
9    mapboxgl.accessToken = window.MAPBOX_ACCESS_TOKEN;
10    const baseStyle = {
11      version: 8,
12      glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf',
13      sources: {
14        'google-street': { type: 'raster', tiles: ['https://mt1.google.com/vt/lyrs=m&x={x}&y={y}&z={z}&scale=2&hl=tr'], tileSize: 512, attribution: '© Google' },
15        'google-satellite': { type: 'raster', tiles: ['https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}&scale=2&hl=tr'], tileSize: 512, attribution: '© Google' },
16        'google-hybrid-overlay': { type: 'raster', tiles: ['https://mt1.google.com/vt/lyrs=h&x={x}&y={y}&z={z}&scale=2&hl=tr'], tileSize: 512, attribution: '© Google' }
17      },
18      layers: [
19        { id: 'google-street-layer', type: 'raster', source: 'google-street', layout: { visibility: 'none' }, minzoom: 0, maxzoom: 22 },
20        { id: 'google-satellite-layer', type: 'raster', source: 'google-satellite', minzoom: 0, maxzoom: 22 },
21        { id: 'google-hybrid-overlay-layer', type: 'raster', source: 'google-hybrid-overlay', paint: { 'raster-opacity': 0.9 }, minzoom: 0, maxzoom: 22 }
22      ]
23    };
24    if (manager) manager._googleBaseStyle = baseStyle;
25    return baseStyle;
26  }
27
28  /** 3D model editörü (Cesium) atmosferine yakın Mapbox gökyüzü — index / drone ile aynı paint. */
29  var PP_SKY_ATMOSPHERE_LAYER_ID = 'pp-sky-atmosphere';
30
31  function ensureProparcelSkyAtmosphereLayer(targetMap) {
32    if (!targetMap || !targetMap.addLayer) return;
33    if (!targetMap.isStyleLoaded || !targetMap.isStyleLoaded()) return;
34
35    // Index harita mercator ile açılır; globe'a geçmek Intel UHD / ANGLE'da
36    // siyah canvas bırakabiliyor (create3DMapInstance yorumuyla aynı).
37    // Sky atmosphere pitch>0 iken mercator üzerinde de çalışır — globe kullanma.
38    try {
39      if (typeof targetMap.setProjection === 'function') {
40        targetMap.setProjection('mercator');
41      }
42    } catch (_) {}
43
44    var paint = {
45      'sky-type': 'atmosphere',
46      'sky-atmosphere-sun': [0.0, 0.0],
47      'sky-atmosphere-sun-intensity': 15,
48      'sky-atmosphere-color': 'rgb(135, 206, 235)',
49      'sky-atmosphere-halo-color': 'rgba(255, 223, 186, 0.5)'
50    };
51    var skyId = null;
52    try {
53      var layers = (targetMap.getStyle && targetMap.getStyle().layers) || [];
54      for (var i = 0; i < layers.length; i++) {
55        if (layers[i] && layers[i].type === 'sky') {
56          skyId = layers[i].id;
57          break;
58        }
59      }
60    } catch (e) {}
61    try {
62      if (skyId) {
63        Object.keys(paint).forEach(function (k) {
64          try {
65            targetMap.setPaintProperty(skyId, k, paint[k]);
66          } catch (_) {}
67        });
68        try {
69          targetMap.setLayoutProperty(skyId, 'visibility', 'visible');
70        } catch (_) {}
71      } else if (!targetMap.getLayer(PP_SKY_ATMOSPHERE_LAYER_ID)) {
72        targetMap.addLayer({ id: PP_SKY_ATMOSPHERE_LAYER_ID, type: 'sky', paint: paint });
73      } else {
74        Object.keys(paint).forEach(function (k) {
75          try {
76            targetMap.setPaintProperty(PP_SKY_ATMOSPHERE_LAYER_ID, k, paint[k]);
77          } catch (_) {}
78        });
79        try {
80          targetMap.setLayoutProperty(PP_SKY_ATMOSPHERE_LAYER_ID, 'visibility', 'visible');
81        } catch (_) {}
82      }
83    } catch (e) {}
84  }
85
86  function create3DMapInstance(manager) {
87    var compat = window.PPWebGLCompat;
88    var forceFlat2D = false;
89    try {
90      forceFlat2D = !!(
91        (compat && typeof compat.supports === 'function' && !compat.supports('3d_mode')) ||
92        (manager && typeof manager._shouldUseLeafletFallback === 'function' && manager._shouldUseLeafletFallback())
93      );
94    } catch (_) {
95      forceFlat2D = true;
96    }
97    // Mercator ile başlat: globe + WebGL bazı sürücülerde uzun süre ana iş parçacığını kilitliyor
98    // (siyah harita, "sayfa yanıt vermiyor"). 3D eğim/kamera yine kullanılabilir.
99    const map3d = new mapboxgl.Map({
100      container: 'map3D',
101      style: createBaseStyle(manager),
102      center: [35.0, 39.0],
103      zoom: 6.5,
104      pitch: 0,
105      bearing: 0,
106      antialias: !forceFlat2D,
107      preserveDrawingBuffer: !forceFlat2D,
108      maxPitch: forceFlat2D ? 0 : 85,
109      minPitch: 0,
110      maxZoom: 22,
111      minZoom: 0,
112      projection: 'mercator'
113    });
114
115    if (manager) {
116      manager.maps = manager.maps || {};
117      manager.maps['3d'] = map3d;
118    }
119    bindCursorWheelZoom(map3d);
120    return map3d;
121  }
122
123  function bindZoomAndNearestRoadLabel(manager, map3d) {
124    const update = () => {
125      const map = (manager && manager.getCurrentMap) ? manager.getCurrentMap() : map3d;
126      if (!map) return;
127      const z = map.getZoom();
128      const el = document.getElementById('map-zoom-indicator');
129      if (el) el.textContent = z.toFixed(1);
130      const labelId = 'nearest_road_field_connector_label';
131      const connId = 'nearest_road_field_connector';
132      if (map.getLayer(labelId) && map.getLayer(connId)) {
133        const vis = map.getLayoutProperty(connId, 'visibility') === 'visible' && z >= (manager.nearestRoadLabelMinZoom || 15);
134        map.setLayoutProperty(labelId, 'visibility', vis ? 'visible' : 'none');
135      }
136    };
137    let _rafId = null;
138    const throttledUpdate = () => {
139      if (_rafId) return;
140      _rafId = requestAnimationFrame(() => { _rafId = null; update(); });
141    };
142    map3d.on('zoom', throttledUpdate);
143    map3d.on('moveend', throttledUpdate);
144    setTimeout(update, 500);
145  }
146
147  /**
148   * TKGM tarzı imleç merkezli tekerlek zoom — around için ekran pikseli değil unproject(lngLat) gerekir.
149   */
150  function bindCursorWheelZoom(map3d) {
151    if (!map3d || map3d.__ppCursorWheelZoomBound) return;
152    var container = map3d.getCanvasContainer && map3d.getCanvasContainer();
153    if (!container) return;
154
155    map3d.__ppCursorWheelZoomBound = true;
156    map3d.scrollZoom.disable();
157
158    container.addEventListener('wheel', function (e) {
159      if (e.ctrlKey || e.metaKey) return;
160      e.preventDefault();
161
162      var rect = container.getBoundingClientRect();
163      var x = e.clientX - rect.left;
164      var y = e.clientY - rect.top;
165      var around;
166      try {
167        around = map3d.unproject([x, y]);
168      } catch (_) {
169        return;
170      }
171
172      var factor = e.deltaMode === WheelEvent.DOM_DELTA_LINE ? 0.05 : 0.002;
173      var next = map3d.getZoom() + (-e.deltaY * factor);
174      var z = Math.max(map3d.getMinZoom(), Math.min(map3d.getMaxZoom(), next));
175
176      try {
177        map3d.zoomTo(z, { around: around, duration: 0 });
178      } catch (_) {}
179    }, { passive: false, capture: true });
180  }
181
182  function bindBasic3DControls(manager, map3d) {
183    map3d.addControl(new mapboxgl.NavigationControl(), 'top-right');
184    map3d.on('click', (e) => {
185      if (e.originalEvent && e.originalEvent.__annotationHandled) return;
186      if (window.enableMapClick && window.proParcelApp?.handleMapClick) window.proParcelApp.handleMapClick(e);
187    });
188    var allowPitch = true;
189    try {
190      if (window.PPWebGLCompat && typeof window.PPWebGLCompat.supports === 'function') {
191        allowPitch = window.PPWebGLCompat.supports('3d_mode');
192      }
193    } catch (_) { allowPitch = false; }
194    if (allowPitch) {
195      map3d.on('wheel', (e) => {
196        if (e.originalEvent?.ctrlKey) {
197          e.preventDefault();
198          map3d.setPitch(Math.max(0, Math.min(85, map3d.getPitch() + e.originalEvent.deltaY * 0.1)));
199        }
200      });
201    }
202    map3d.on('webglcontextlost', (e) => {
203      try { if (e && e.preventDefault) e.preventDefault(); } catch (_) {}
204      try {
205        if (window.PPWebGLCompat && typeof window.PPWebGLCompat.recordContextLost === 'function') {
206          window.PPWebGLCompat.recordContextLost();
207        }
208      } catch (_) {}
209    });
210  }
211
212  // --- EXPORT EDİLEN CORE FONKSİYONLAR ---
213
214  window.MapManagerCore.createBaseStyle = createBaseStyle;
215  window.MapManagerCore.create3DMapInstance = create3DMapInstance;
216  window.MapManagerCore.bindCursorWheelZoom = bindCursorWheelZoom;
217
218  /** Style yüklü değilse kısa timeout ile bekle — idle beklemek geçişi gereksiz uzatır. */
219  window.MapManagerCore.waitForStyleLoaded = function (map, timeoutMs) {
220    const targetMap = map;
221    const ms = typeof timeoutMs === 'number' ? timeoutMs : 2000;
222    if (!targetMap) return Promise.resolve();
223    try {
224      if (targetMap.isStyleLoaded && targetMap.isStyleLoaded()) return Promise.resolve();
225    } catch (_) {}
226    return new Promise((resolve) => {
227      let done = false;
228      const finish = () => {
229        if (done) return;
230        done = true;
231        resolve();
232      };
233      try {
234        targetMap.once('style.load', finish);
235      } catch (_) {}
236      setTimeout(finish, ms);
237    });
238  };
239
240  /** idle veya timeout — zaten idle ise kısa repaint sonrası hemen çözülür. */
241  window.MapManagerCore.waitForMapIdle = function (map, timeoutMs) {
242    const targetMap = map;
243    const ms = typeof timeoutMs === 'number' ? timeoutMs : 2500;
244    if (!targetMap) return Promise.resolve();
245    return new Promise((resolve) => {
246      let done = false;
247      const finish = () => {
248        if (done) return;
249        done = true;
250        resolve();
251      };
252      try {
253        targetMap.once('idle', finish);
254        if (typeof targetMap.triggerRepaint === 'function') targetMap.triggerRepaint();
255      } catch (_) {}
256      setTimeout(finish, ms);
257    });
258  };
259
260  window.MapManagerCore.ensureTerrain = async function (manager, map) {
261    const targetMap = map || manager?.maps?.['3d'];
262    if (!targetMap) return;
263
264    try {
265      if (window.PPWebGLCompat && typeof window.PPWebGLCompat.supports === 'function' && !window.PPWebGLCompat.supports('terrain')) {
266        return;
267      }
268    } catch (_) {}
269
270    const is3D = !!manager?.is3DMode;
271
272    // Yalnızca style yeterli; idle beklemek 2D↔3D geçişini şişiriyordu.
273    await window.MapManagerCore.waitForStyleLoaded(targetMap, 2000);
274
275    // DEM source'u 2D'de de tut (ön ısıtma) — toggle'da source ekleme maliyeti olmasın
276    if (!targetMap.getSource('mapbox-dem')) {
277      try {
278        targetMap.addSource('mapbox-dem', {
279          type: 'raster-dem',
280          url: 'mapbox://mapbox.mapbox-terrain-dem-v1',
281          tileSize: 512,
282          maxzoom: 14
283        });
284      } catch (_) {}
285    }
286
287    try {
288      if (is3D) {
289        targetMap.setTerrain({ source: 'mapbox-dem', exaggeration: 1.8 });
290        if (!targetMap.getLayer('terrain-hillshade')) {
291          targetMap.addLayer({
292            id: 'terrain-hillshade',
293            type: 'hillshade',
294            source: 'mapbox-dem',
295            paint: { 'hillshade-exaggeration': 0.5 }
296          });
297        } else {
298          targetMap.setLayoutProperty('terrain-hillshade', 'visibility', 'visible');
299        }
300      } else {
301        targetMap.setTerrain(null);
302        if (targetMap.getLayer('terrain-hillshade')) {
303          targetMap.setLayoutProperty('terrain-hillshade', 'visibility', 'none');
304        }
305      }
306    } catch (terrainErr) {
307      try {
308        targetMap.setTerrain(null);
309        if (targetMap.getLayer('terrain-hillshade')) {
310          targetMap.setLayoutProperty('terrain-hillshade', 'visibility', 'none');
311        }
312      } catch (_) {}
313      if (window.PPWebGLCompat && typeof window.PPWebGLCompat.logCapabilities === 'function') {
314        window.PPWebGLCompat.logCapabilities(true);
315      }
316    }
317  };
318
319  window.MapManagerCore.restoreEssentialLayers = function (manager, map) {
320    const targetMap = map || manager?.maps?.['3d'];
321    if (!targetMap) return Promise.resolve();
322
323    // Terrain'i her zaman çağır (kendi içinde is3D kontrolü yapar); Promise döndür
324    const terrainP = window.MapManagerCore.ensureTerrain(manager, targetMap).catch(() => {});
325
326    if (!targetMap.isStyleLoaded()) return terrainP;
327
328    const style = targetMap.getStyle();
329    const isGoogle = !!(style?.sources?.['google-satellite'] || style?.sources?.['google-hybrid-overlay']);
330    if (isGoogle) {
331      ensureProparcelSkyAtmosphereLayer(targetMap);
332      return terrainP;
333    }
334
335    var allowExtrusion = true;
336    try {
337      if (window.PPWebGLCompat && typeof window.PPWebGLCompat.supports === 'function') {
338        allowExtrusion = window.PPWebGLCompat.supports('extrusion');
339      }
340    } catch (_) { allowExtrusion = false; }
341
342    // Binalar
343    if (allowExtrusion && !targetMap.getLayer('3d-buildings')) {
344      if (!targetMap.getSource('mapbox-buildings')) {
345        targetMap.addSource('mapbox-buildings', { type: 'vector', url: 'mapbox://mapbox.mapbox-streets-v8' });
346      }
347      targetMap.addLayer({
348        id: '3d-buildings', source: 'mapbox-buildings', 'source-layer': 'building', type: 'fill-extrusion', minzoom: 12,
349        paint: {
350          'fill-extrusion-color': ['case', ['==', ['get', 'type'], 'residential'], '#FF6B6B', ['==', ['get', 'type'], 'commercial'], '#4ECDC4', '#95A5A6'],
351          'fill-extrusion-height': ['interpolate', ['linear'], ['zoom'], 14, 0, 14.5, ['*', ['get', 'height'], 0.8]],
352          'fill-extrusion-base': ['get', 'min_height'], 'fill-extrusion-opacity': 0.8
353        }
354      });
355    }
356
357    ensureProparcelSkyAtmosphereLayer(targetMap);
358    return terrainP;
359  };
360
361  window.MapManagerCore.initialize3DMap = async function (manager) {
362    const container = document.getElementById('map3D');
363    if (!container || !window.MAPBOX_ACCESS_TOKEN) return null;
364
365    if (manager?.maps?.['3d']) {
366      manager.maps['3d'].off();
367      manager.maps['3d'].remove();
368    }
369
370    const map3d = create3DMapInstance(manager);
371    bindZoomAndNearestRoadLabel(manager, map3d);
372    bindBasic3DControls(manager, map3d);
373
374    map3d.on('style.load', () => window.MapManagerCore.restoreEssentialLayers(manager, map3d));
375    
376    return map3d;
377  };
378
379  window.MapManagerCore.hideCloudAndShadowLayers = function (manager, map) {
380    const targetMap = map || manager?.maps?.['3d'];
381    const layers = targetMap?.getStyle()?.layers;
382    if (!layers) return;
383    const targets = ['cloud', 'shadow', 'atmosphere', 'fog', 'sky', 'haze'];
384    layers.forEach(l => {
385      if (!l || !l.id) return;
386      if (l.id.indexOf('pp-sky') === 0) return;
387      if (targets.some(t => l.id.includes(t)) && !l.id.includes('terrain') && !l.id.includes('dem')) {
388        targetMap.setLayoutProperty(l.id, 'visibility', 'none');
389      }
390    });
391  };
392
393  window.MapManagerCore.addNasaSatelliteLayer = function (manager, map) {
394    const targetMap = map || manager?.maps?.['3d'];
395    if (!targetMap) return;
396    if (!targetMap.getSource('nasa-satellite')) {
397      targetMap.addSource('nasa-satellite', { type: 'raster', tiles: ['https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}'], tileSize: 256, attribution: '© NASA' });
398    }
399    if (!targetMap.getLayer('nasa-satellite-layer')) {
400      targetMap.addLayer({ id: 'nasa-satellite-layer', type: 'raster', source: 'nasa-satellite', paint: { 'raster-opacity': 1.0 } }, 'background');
401    }
402  };
403
404  window.MapManagerCore.waitForStableRender = function (manager, minWait = 500) {
405    const map = manager?.maps?.['3d'];
406    if (!map) return Promise.resolve();
407    const idleWait = window.MapManagerCore.waitForMapIdle
408      ? window.MapManagerCore.waitForMapIdle(map, Math.max(800, minWait + 400))
409      : Promise.resolve();
410    return idleWait.then(() => new Promise((resolve) => setTimeout(resolve, minWait)));
411  };
412})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.