fix(map): هم‌گام‌سازی بوم با ResizeObserver و کف ارتفاع ظرف — در حالت موبایل/DevTools پس از تغییر viewport نقشه ناقص و خالی می‌ماند

This commit is contained in:
aramesh-site deploy
2026-10-09 18:10:27 +00:00
parent 324298c9d7
commit 7d78a1fc58
2 changed files with 21 additions and 2 deletions
+2 -2
View File
@@ -66,7 +66,7 @@ export function MapViewport({
const shellClass = isFullscreen
? 'fixed inset-0 z-[75] h-[100dvh] w-screen animate-[luxFadeIn_0.25s_ease-out] rounded-none border-0'
: `relative h-full w-full rounded-3xl border border-ivory/10 shadow-lift ${className}`
: `relative h-full min-h-[280px] w-full rounded-3xl border border-ivory/10 shadow-lift ${className}`
return (
<div
@@ -78,7 +78,7 @@ export function MapViewport({
است تا هم بستر موقعیت‌یابی فرزندان مپ‌لیبر باشد و هم هشدار
«container has a non-static position» و محاسبه‌ی اشتباه آفست اسکرول
رخ ندهد — ترتیب بار شدن CSS هیچ‌وقت تعیین‌کننده نباشد */}
<div ref={containerRef} className="relative h-full w-full" />
<div ref={containerRef} className="relative h-full min-h-[280px] w-full" />
{isFullscreen ? (
<button
+19
View File
@@ -50,6 +50,7 @@ export function useMapLibre({ center, zoom, scrollZoom = true, maxBounds, minZoo
let disposed = false
let instance: maplibregl.Map | null = null
const cleanups: Array<() => void> = []
let readyFallback: number | undefined
let dprQuery: MediaQueryList | null = null
let handleDprChange: (() => void) | null = null
@@ -128,9 +129,26 @@ export function useMapLibre({ center, zoom, scrollZoom = true, maxBounds, minZoo
instance.on('style.load', () => {
if (disposed) return
setStatus('ready')
// یک هم‌گام‌سازی پس از چیدمان نهایی (فونت/تصویر ممکن است ارتفاع را عوض کند)
window.setTimeout(() => instance?.resize(), 150)
})
/**
* هم‌گام‌سازی مداوم بوم با اندازهٔ واقعی ظرف.
*
* تایمرهای ثابت کافی نیستند: در حالت موبایل DevTools و روی گوشی واقعی،
* ظرف پس از ساخته‌شدن نقشه تغییر اندازه می‌دهد (اعمال viewport شبیه‌سازی‌شده،
* جمع/باز شدن نوار آدرس، چرخش صفحه). در آن حالت بوم با اندازهٔ قدیمی
* می‌ماند و نقشه ناقص/تاریخ‌شده دیده می‌شود. ResizeObserver دقیقاً همان
* لحظه خبر می‌دهد و resize روی همان فریم اعمال می‌شود.
*/
const sizeObserver = new ResizeObserver(() => {
if (disposed || !instance) return
instance.resize()
})
sizeObserver.observe(container)
cleanups.push(() => sizeObserver.disconnect())
/**
* کنترل بزرگ‌نمایی همراه خود نقشه ساخته می‌شود و با map.remove() پایین
* می‌آید — map.remove به‌تنهایی onRemove همه‌ی کنترل‌ها را صدا می‌زند،
@@ -203,6 +221,7 @@ export function useMapLibre({ center, zoom, scrollZoom = true, maxBounds, minZoo
window.clearTimeout(timeoutId)
if (readyFallback !== undefined) window.clearTimeout(readyFallback)
if (dprQuery && handleDprChange) dprQuery.removeEventListener('change', handleDprChange)
cleanups.forEach((fn) => fn())
controller.abort()
instance?.remove()
}