اگر کدی نوشتهاید که با یک کتابخانه نقشه ارتباط دارد، کدی نوشتهاید که با viewport ارتباط دارد. Viewport state زمان اجرای نقشه است: کجا مرکزیت دارد، چقدر zoom شده، به کدام سمت نگاه میکند و اختیاری چقدر tilt دارد. هر pan، zoom، چرخش و کلیک به آن بستگی دارد.
این راهنما توضیح میدهد viewport واقعاً چیست، چهار مقدار اصلی که آن را توصیف میکنند، چطور با tile ها و bounding boxها تعامل دارد و الگوهای production برای ذخیره، بازیابی و اشتراکگذاری state viewport.
چهار مقدار اصلی
یک viewport نقشه وب مدرن با حداکثر چهار مقدار توصیف میشود:
- Center (
{ lat, lng }): مختصات جغرافیایی در وسط صفحه. - Zoom (یک عدد، اغلب float): چقدر نقشه zoom شده. اعداد بالاتر مناطق کوچکتر را با جزئیات بیشتر نشان میدهند.
- Bearing (یک عدد بر حسب درجه، پیشفرض 0): چرخش نقشه از "شمال به بالا". ۹۰ یعنی شرق به بالاست.
- Pitch (یک عدد بر حسب درجه، ۰ تا ~۸۵): tilt سهبعدی. ۰ مستوی از بالا به پایین است، ۶۰ یک دید perspective قوی است.
هر کتابخانه نقشه مدرن (MapLibre GL، Mapbox GL، OpenLayers، Leaflet، MapAtlas Dynamic Maps) اینها را به عنوان state قابل خواندن و نوشتن expose میکند. یک کتابخانه فقط ۲D مثل Leaflet ممکن است bearing یا pitch را expose نکند.
سطح Zoom به تفصیل
سطح zoom بیشترین سوالخورترین مورد از چهار مقدار است. یک عدد صحیح (یا کسری) است که جهان را به یک هرم tile نگاشت میکند:
- Zoom 0: کل جهان در یک tile ۲۵۶×۲۵۶
- Zoom 1: جهان در ۴ tile تقسیم شده
- Zoom 2: ۱۶ tile
- ...
- Zoom 14: ~۲۶۸ میلیون tile، مقیاس محلهای
- Zoom 18: مقیاس ساختمانی
- Zoom 22+: معمولاً با upscaling استایل vector رندر میشود نه داده tile تازه
یک قانون انگشتی مفید در خط استوا: هر افزایش سطح zoom عرض قابل مشاهده روی صفحه را نصف میکند. در zoom 14، یک صفحه معمولاً چند بلوک شهری را نشان میدهد. در zoom 10، یک منطقه شهری. در zoom 6، یک کشور.
اکثر کدهای production zoom را به صورت float ذخیره میکنند (مثلاً ۱۴.۵) چون انیمیشنهای zoom روان بین zoom های صحیح interpolate میکنند.
Viewport در مقابل Bounding Box
یک viewport state دوربین است. یک bounding box مستطیل جغرافیایی در حال حاضر قابل مشاهده است. هر بار که نیاز دارید از سرور بپرسید "چه چیزی باید داخل این view نشان دهم؟" bbox را از viewport محاسبه میکنید.
در کد:
const bbox = map.getBounds(); // returns { _sw: {lat, lng}, _ne: {lat, lng} }
const params = new URLSearchParams({
bbox: `${bbox._sw.lng},${bbox._sw.lat},${bbox._ne.lng},${bbox._ne.lat}`,
});
const features = await fetch(`/api/places?${params}`).then(r => r.json());
این الگو (محاسبه bbox از viewport، ارسال به سرور، رندر feature های برگرداندهشده) ضربان قلب هر تجربه جستجوی مبتنی بر viewport است: مسکن، لیستها، store locator، ردیابی ناوگان، ride-share.
چطور Viewport بارگذاری Tile را هدایت میکند
وقتی viewport تغییر میکند، کتابخانه نقشه تشخیص میدهد کدام tile ها منطقه قابل مشاهده جدید را در سطح zoom فعلی پوشش میدهند، هر tile مفقود را از سرور (یا cache درونحافظهای) fetch میکند و آنها را رندر میکند. Tile های از پیش cached استفاده مجدد میشوند؛ tile های خارج از viewport برای صورتی که کاربر به عقب pan کند نگه داشته میشوند.
یک pan و zoom روان بدون درز احساس میشود چون کتابخانه این کار را به صورت asynchronous انجام میدهد: آنچه دارد را میکشد، آنچه نیاز دارد را fetch میکند و canvas را با رسیدن tile های جدید بهروز میکند.
ذخیره و اشتراکگذاری State Viewport
ذخیره viewport در URL الگوی استاندارد برای لینکهای نقشه قابل اشتراکگذاری است. اکثر محصولات از یک URL hash مثل #map=14.5/52.5200/13.4050 (zoom، lat، lng) استفاده میکنند. در page load، hash را parse کنید و viewport را اعمال کنید. در تغییر viewport، چند صد میلیثانیه debounce کنید و hash را بهروز کنید تا دکمه back مرورگر مفید بماند.
برای state داخلی مرورگر در tab ها یا session ها، یک کلید localStorage با همان شکل کار میکند. برای صفحههای server-rendered، viewport اغلب به صورت query params برای URL های SEO-friendly ظاهر میشود (?zoom=14&lat=52.52&lng=13.405).
Viewport Bias برای جستجو و Autocomplete
APIهای Geocoding viewport (یا bbox آن) را به عنوان پارامتر bias میپذیرند. MapAtlas برای فیلتر سخت boundary.rect.* و برای bias نرم focus.point.* را expose میکند. بدون bias، autocomplete برای "اصفهان" هر اصفهانی با بیشترین محبوبیت جهانی برمیگرداند. با viewport bias، کاربر که داخل نقشه خود از اصفهان تایپ میکند اول نتایج اصفهان اصلی را میگیرد.
این bias را روی هر keystroke اعمال کنید. هزینه آن یک پارامتر است و پیشنهادات بهطور قابل توجهی مرتبطتر میشوند.
Viewport اولیه: کجا شروع کنیم
اولین چیزی که هر برنامه نقشه باید تصمیم بگیرد این است که کجا شروع کند. الگوهای رایج:
- پیشفرض به locale کاربر: یک کاربر در ایران روی یک viewport بالای تهران میرسد.
- پیشفرض به آخرین viewport کاربر: viewport را در session ها حفظ کنید.
- پیشفرض به داده: اگر نقشه شما نتایج جستجو نشان میدهد، bbox آن نتایج را در رندر اولیه fit کنید.
- پیشفرض به IP geolocation کاربر: دقت پایین، نیاز به مجوز ندارد، fallback خوبی است.
- درخواست browser geolocation فقط وقتی کاربر صراحتاً موافقت میکند: هرگز در load اول بدون رضایت UI.
انتخاب یک viewport اولیه معقول یک جزئیات کوچک با تأثیر بزرگ بر کیفیت درکشده است.
چطور MapAtlas State Viewport را Expose میکند
کامپوننت Dynamic Maps MapAtlas همان API getCenter، getZoom، getBearing، getPitch و setView که هر نقشه وب developer-grade ارائه میدهد را expose میکند، با علاوه بر آن میزبانی فقط در EU و پارامترهای viewport bias سازگار در endpoint های Geocoding و Search. برای بررسی عمیقتر نحوه تعامل viewport با tile ها و projectionها، What Is a Vector Tile و What Is Web Mercator را ببینید.
سوالات متداول
Map viewport چیست؟
یک map viewport پنجره قابل مشاهده یک نقشه است: منطقه جغرافیایی که در حال حاضر روی صفحه نمایش داده میشود، که با یک مختصات مرکز (عرض و طول جغرافیایی)، یک سطح zoom (چقدر به داخل یا خارج zoom شده)، و اختیاری یک bearing (چرخش) و pitch (tilt سهبعدی) توصیف میشود. هر نقشه وب مدرن (Google Maps، MapLibre، Mapbox GL، MapAtlas) viewport را به عنوان state که میتوانید به صورت برنامهنویسی بخوانید و تنظیم کنید expose میکند.
سطح zoom چیست؟
سطح zoom یک عدد صحیح (یا کسری) است که کنترل میکند چقدر از جهان در یک tile با اندازه ثابت قابل مشاهده است. Zoom 0 کل جهان را در یک tile ۲۵۶×۲۵۶ جا میدهد. هر سطح zoom بعدی رزولوشن را دو برابر میکند: zoom 1 چهار tile، zoom 2 شانزده تا دارد. Zoom 14 تقریباً مقیاس محلهای است، zoom 18 تقریباً مقیاس ساختمانی.
تفاوت بین viewport و bounding box چیست؟
یک viewport state دوربین است (مرکز، zoom، bearing، pitch). یک bounding box مستطیل جغرافیایی است که دوربین در حال حاضر نشان میدهد. bbox را از viewport محاسبه میکنید: با داشتن مرکز، zoom و اندازه صفحه، کتابخانه نقشه محاسبه میکند کدام مستطیل lat/lng قابل مشاهده است. Bbox همان چیزی است که به geocoding API به عنوان viewport bias میفرستید، پایگاه داده را با آن برای ویژگیهای قابل مشاهده کوئری میکنید و وقتی میخواهید بدانید کاربر به چه چیزی نگاه میکرد ثبت میکنید.
چطور یک map viewport را ذخیره و بازیابی کنم؟
چهار مقدار اصلی (عرض جغرافیایی مرکز، طول جغرافیایی مرکز، zoom، bearing اگر از چرخش پشتیبانی میکنید) را به URL یا local storage serialize کنید. یک الگوی رایج یک hash مثل #map=14.5/52.5200/13.4050 برای zoom 14.5 در مرکز برلین است. MapAtlas، MapLibre و Mapbox GL همه یک API برای getCenter / getZoom / getBearing و معادل setView expose میکنند.

