diff --git a/frontend/src/map/useMapLibre.ts b/frontend/src/map/useMapLibre.ts index 0fa64ec..556e8d9 100644 --- a/frontend/src/map/useMapLibre.ts +++ b/frontend/src/map/useMapLibre.ts @@ -53,6 +53,13 @@ export function useMapLibre({ center, zoom, scrollZoom = true, maxBounds, minZoo let readyFallback: number | undefined let dprQuery: MediaQueryList | null = null let handleDprChange: (() => void) | null = null + // آیا می‌توان کانتکست آنتی‌آلیاسه گرفت؟ (تست سبک، یک‌بار در هر ساخت نقشه) + const probeCanvas = document.createElement('canvas') + const canAntialias = Boolean( + probeCanvas.getContext('webgl2', { antialias: true }) || + probeCanvas.getContext('webgl', { antialias: true }), + ) + const controller = new AbortController() const timeoutId = window.setTimeout(() => controller.abort(), STYLE_TIMEOUT_MS) @@ -61,6 +68,16 @@ export function useMapLibre({ center, zoom, scrollZoom = true, maxBounds, minZoo // وب‌ورکر نقشه و پروتکل pmtiles باید پیش از ساخت نقشه آماده باشند؛ // وگرنه نخستین درخواست‌های کاشی در وب‌ورکر بی‌پاسخ می‌مانند + // پیش‌سنجی WebGL: برخی مرورگرهای موبایل (یا حالت ذخیرهٔ باتری/داده) کانتکست + // WebGL نمی‌دهند. بدون این بررسی، سازندهٔ مپ‌لیبر خطا می‌دهد و صفحه در حالت + // «در حال بارگذاری» گیر می‌کند — کاربر فقط یک قاب خالی می‌بیند. + const probe = document.createElement('canvas') + const gl = probe.getContext('webgl2') || probe.getContext('webgl') || probe.getContext('experimental-webgl') + if (!gl) { + setStatus('error') + return + } + Promise.all([loadMapStyle(controller.signal), ensureMapWorker()]) .then(([style]) => { if (disposed) return @@ -75,7 +92,9 @@ export function useMapLibre({ center, zoom, scrollZoom = true, maxBounds, minZoo maxZoom: FALLBACK_MAX_ZOOM, renderWorldCopies: false, // لبه‌های نرم‌تر خطوط و چندضلعی‌ها — حس لوکس رندر برداری - canvasContextAttributes: { antialias: true }, + // antialias فقط جایی که مطمئنیم پشتیبانی می‌شود — درخواست بی‌قید آن + // روی بعضی GPUهای موبایل کانتکست را رد می‌کند و نقشه ساخته نمی‌شود. + canvasContextAttributes: { antialias: canAntialias }, // کیفیت حداکثری در بزرگ‌نمایی‌های عمیق: هیچ سطحی با مقیاس‌کردن سطح // بالاتر رندر نمی‌شود و همه‌ی سطح‌ها تا maxZoom از تقسیم هندسه // می‌آیند (پیش‌فرض ۴ سطح آخر را overscale می‌کند). مبادله: کار @@ -173,7 +192,9 @@ export function useMapLibre({ center, zoom, scrollZoom = true, maxBounds, minZoo setMap(instance) }) - .catch(() => { + .catch((error) => { + // خطای ساخت/بارگذاری نقشه — وضعیت خطا با پیام قابل‌تلاش‌دوباره، نه قاب خالی + console.warn('[map] راه‌اندازی نقشه ناموفق بود:', error) if (!disposed) setStatus('error') })