feat(map): زوماوت آزاد تا دید کشوری، قاب نخست روی همهٔ پروژهها با fitBounds، و تصاویر دیتابیس در پاپآپ نقشه
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { createPortal } from 'react-dom'
|
||||
import { useMemo } from 'react'
|
||||
import { useEffect, useMemo } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { MdArrowBack, MdOpenInNew } from 'react-icons/md'
|
||||
import {
|
||||
@@ -32,8 +32,8 @@ export type ProjectsMapAllProps = {
|
||||
/**
|
||||
* نمای «همهی پروژهها» — همهی مختصات شیت روی یک نقشهی تمامعرض با
|
||||
* سنجاقهای مسی، پاپآپ کارتی و دو اکشن عمودی: صفحهی پروژه و آدرس نشان.
|
||||
* پاپآپ فقط با کلیک کاربر باز میشود و جابهجایی نقشه به محدودهٔ پروژهها
|
||||
* بسته است.
|
||||
* پاپآپ فقط با کلیک کاربر باز میشود؛ نمای نخست همهی سنجاقها را در قاب
|
||||
* دارد و زوماوت تا دید کشوری آزاد است.
|
||||
*/
|
||||
export function ProjectsMapAll({
|
||||
className = '',
|
||||
@@ -43,9 +43,21 @@ export function ProjectsMapAll({
|
||||
}: ProjectsMapAllProps) {
|
||||
const { t, href } = useLang()
|
||||
const bounds = useMemo(() => boundsForProjects(projects), [projects])
|
||||
const { containerRef, map, status, retry } = useMapLibre({ center: ISFAHAN_CENTER, zoom: 12, maxBounds: bounds })
|
||||
// بدون maxBounds — زوماوت آزاد تا کف زوم ۵ (دید کشوری)؛ نمای نخست با fitBounds
|
||||
// همهٔ سنجاقها را در یک قاب مینشیند.
|
||||
const { containerRef, map, status, retry } = useMapLibre({
|
||||
center: ISFAHAN_CENTER,
|
||||
zoom: 12,
|
||||
minZoom: 5,
|
||||
})
|
||||
const { popupHost, activeProject, closePopup } = useProjectMarkers(map, projects)
|
||||
|
||||
// نمای نخست: قاب همهٔ پروژهها — بعد از آمادهشدن نقشه یکبار اجرا میشود
|
||||
useEffect(() => {
|
||||
if (!map || !bounds) return
|
||||
map.fitBounds(bounds, { padding: 48, maxZoom: 14, duration: 0 })
|
||||
}, [map, bounds])
|
||||
|
||||
const projectHref = href((activeProject && resolveProjectHref?.(activeProject)) || '/projects')
|
||||
const images = activeProject ? (imagesFor?.(activeProject) ?? []) : []
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ type UseMapLibreOptions = {
|
||||
scrollZoom?: boolean
|
||||
/** محدودهٔ مجاز جابهجایی نقشه — جلوگیری از رفتن به بیرون محدودهٔ پروژهها */
|
||||
maxBounds?: maplibregl.LngLatBoundsLike
|
||||
/** کف بزرگنمایی — زوماوت بیمعنا روی نقشهٔ خالی را میبندد */
|
||||
minZoom?: number
|
||||
}
|
||||
|
||||
/** سقف انتظار سبک نقشه — سرور کاشی بیپاسخ یعنی خطای قابل تلاش دوباره، نه اسپینر بیپایان */
|
||||
@@ -36,7 +38,7 @@ const ABSOLUTE_MAX_ZOOM = 22
|
||||
/** سقف جایگزین وقتی maxzoom منبع در دسترس نیست — برابر آرشیو فعلی (z14 + ۳) */
|
||||
const FALLBACK_MAX_ZOOM = 17
|
||||
|
||||
export function useMapLibre({ center, zoom, scrollZoom = true, maxBounds }: UseMapLibreOptions) {
|
||||
export function useMapLibre({ center, zoom, scrollZoom = true, maxBounds, minZoom }: UseMapLibreOptions) {
|
||||
const containerRef = useRef<HTMLDivElement | null>(null)
|
||||
const [map, setMap] = useState<maplibregl.Map | null>(null)
|
||||
const [status, setStatus] = useState<MapStatus>('loading')
|
||||
@@ -68,6 +70,7 @@ export function useMapLibre({ center, zoom, scrollZoom = true, maxBounds }: UseM
|
||||
center,
|
||||
zoom,
|
||||
maxBounds,
|
||||
minZoom,
|
||||
// سقف اولیه تا رسیدن maxzoom واقعی منبع؛ سپس applyZoomLimit دقیق میکند
|
||||
maxZoom: FALLBACK_MAX_ZOOM,
|
||||
renderWorldCopies: false,
|
||||
|
||||
@@ -81,6 +81,17 @@ export function Projects() {
|
||||
return dbMatch ? `/projects/${dbMatch.slug}` : undefined;
|
||||
};
|
||||
|
||||
// تصاویر پاپآپ نقشه — تصویر شاخص + گالری پروژهٔ متناظر در دیتابیس؛
|
||||
// پروژهٔ بدون تصویر یا بدون متناظر، جاینگهدار میگیرد.
|
||||
const imagesFor = (mapProject: MapProject): string[] => {
|
||||
const dbMatch = dbProjects.find(
|
||||
(p) => p.title === mapProject.name || p.title_en === mapProject.name,
|
||||
);
|
||||
if (!dbMatch) return [];
|
||||
const gallery = Array.isArray(dbMatch.gallery) ? dbMatch.gallery : [];
|
||||
return [dbMatch.image, ...gallery].filter((src): src is string => !!src);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHero pageKey="projects" />
|
||||
@@ -92,6 +103,7 @@ export function Projects() {
|
||||
<LazyProjectsMapAll
|
||||
projects={MAP_PROJECTS}
|
||||
resolveProjectHref={resolveProjectHref}
|
||||
imagesFor={imagesFor}
|
||||
className="h-[350px] md:h-[450px] lg:h-[55vh] max-h-[600px] w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user