fix(map): همگامسازی بوم با ResizeObserver و کف ارتفاع ظرف — در حالت موبایل/DevTools پس از تغییر viewport نقشه ناقص و خالی میماند
This commit is contained in:
@@ -66,7 +66,7 @@ export function MapViewport({
|
|||||||
|
|
||||||
const shellClass = isFullscreen
|
const shellClass = isFullscreen
|
||||||
? 'fixed inset-0 z-[75] h-[100dvh] w-screen animate-[luxFadeIn_0.25s_ease-out] rounded-none border-0'
|
? '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 (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -78,7 +78,7 @@ export function MapViewport({
|
|||||||
است تا هم بستر موقعیتیابی فرزندان مپلیبر باشد و هم هشدار
|
است تا هم بستر موقعیتیابی فرزندان مپلیبر باشد و هم هشدار
|
||||||
«container has a non-static position» و محاسبهی اشتباه آفست اسکرول
|
«container has a non-static position» و محاسبهی اشتباه آفست اسکرول
|
||||||
رخ ندهد — ترتیب بار شدن CSS هیچوقت تعیینکننده نباشد */}
|
رخ ندهد — ترتیب بار شدن CSS هیچوقت تعیینکننده نباشد */}
|
||||||
<div ref={containerRef} className="relative h-full w-full" />
|
<div ref={containerRef} className="relative h-full min-h-[280px] w-full" />
|
||||||
|
|
||||||
{isFullscreen ? (
|
{isFullscreen ? (
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ export function useMapLibre({ center, zoom, scrollZoom = true, maxBounds, minZoo
|
|||||||
|
|
||||||
let disposed = false
|
let disposed = false
|
||||||
let instance: maplibregl.Map | null = null
|
let instance: maplibregl.Map | null = null
|
||||||
|
const cleanups: Array<() => void> = []
|
||||||
let readyFallback: number | undefined
|
let readyFallback: number | undefined
|
||||||
let dprQuery: MediaQueryList | null = null
|
let dprQuery: MediaQueryList | null = null
|
||||||
let handleDprChange: (() => void) | null = null
|
let handleDprChange: (() => void) | null = null
|
||||||
@@ -128,9 +129,26 @@ export function useMapLibre({ center, zoom, scrollZoom = true, maxBounds, minZoo
|
|||||||
instance.on('style.load', () => {
|
instance.on('style.load', () => {
|
||||||
if (disposed) return
|
if (disposed) return
|
||||||
setStatus('ready')
|
setStatus('ready')
|
||||||
|
// یک همگامسازی پس از چیدمان نهایی (فونت/تصویر ممکن است ارتفاع را عوض کند)
|
||||||
window.setTimeout(() => instance?.resize(), 150)
|
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() پایین
|
||||||
* میآید — map.remove بهتنهایی onRemove همهی کنترلها را صدا میزند،
|
* میآید — map.remove بهتنهایی onRemove همهی کنترلها را صدا میزند،
|
||||||
@@ -203,6 +221,7 @@ export function useMapLibre({ center, zoom, scrollZoom = true, maxBounds, minZoo
|
|||||||
window.clearTimeout(timeoutId)
|
window.clearTimeout(timeoutId)
|
||||||
if (readyFallback !== undefined) window.clearTimeout(readyFallback)
|
if (readyFallback !== undefined) window.clearTimeout(readyFallback)
|
||||||
if (dprQuery && handleDprChange) dprQuery.removeEventListener('change', handleDprChange)
|
if (dprQuery && handleDprChange) dprQuery.removeEventListener('change', handleDprChange)
|
||||||
|
cleanups.forEach((fn) => fn())
|
||||||
controller.abort()
|
controller.abort()
|
||||||
instance?.remove()
|
instance?.remove()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user