Nếu bạn đã viết bất kỳ code nào giao tiếp với thư viện bản đồ, bạn đã viết code đụng đến viewport. Viewport là trạng thái runtime của bản đồ: nó được căn tâm ở đâu, phóng to bao nhiêu, đang chỉ hướng nào, và tùy chọn nghiêng bao nhiêu. Mọi pan, zoom, xoay và click đều phụ thuộc vào nó.
Hướng dẫn này giải thích viewport thực sự là gì, bốn giá trị cốt lõi mô tả nó, cách nó tương tác với tile và bounding box, và các production pattern để lưu, khôi phục và chia sẻ trạng thái viewport.
Bốn Giá Trị Cốt Lõi
Viewport bản đồ web hiện đại được mô tả bởi tối đa bốn giá trị:
- Center (
{ lat, lng }): tọa độ địa lý ở giữa màn hình. - Zoom (một số, thường là float): bản đồ được phóng to bao nhiêu. Số cao hơn hiển thị khu vực nhỏ hơn với nhiều chi tiết hơn.
- Bearing (một số tính bằng độ, mặc định 0): góc xoay của bản đồ từ "hướng bắc lên". 90 nghĩa là hướng đông lên.
- Pitch (một số tính bằng độ, 0 đến ~85): nghiêng 3D. 0 là phẳng nhìn từ trên xuống, 60 là góc nhìn phối cảnh mạnh.
Mọi thư viện bản đồ hiện đại (MapLibre GL, Mapbox GL, OpenLayers, Leaflet, MapAtlas Dynamic Maps) đều expose chúng như state có thể đọc và ghi. Thư viện chỉ 2D như Leaflet có thể không expose bearing hay pitch.
Chi Tiết Về Zoom Level
Zoom level là câu hỏi được hỏi nhiều nhất trong bốn giá trị. Đây là số nguyên (hoặc thập phân) ánh xạ thế giới vào hình kim tự tháp tile:
- Zoom 0: toàn bộ thế giới trong một tile 256x256
- Zoom 1: thế giới chia thành 4 tile
- Zoom 2: 16 tile
- ...
- Zoom 14: ~268 triệu tile, quy mô khu phố
- Zoom 18: quy mô tòa nhà
- Zoom 22+: thường được render với vector style upscaling thay vì dữ liệu tile mới
Một quy tắc ngón tay hữu ích ở đường xích đạo: mỗi lần tăng mức zoom giảm một nửa chiều rộng hiển thị trên màn hình. Ở zoom 14, một màn hình thường hiển thị vài dãy phố thành phố. Ở zoom 10, một khu vực đô thị. Ở zoom 6, một quốc gia. Độ phân giải hiệu quả phụ thuộc vào kích thước màn hình và hình chiếu (Web Mercator méo bắc-nam khi bạn tiến về phía cực).
Hầu hết code production lưu zoom dưới dạng float (ví dụ 14.5) vì animation zoom mượt mà nội suy giữa các mức zoom nguyên. Tile fetch xảy ra ở mức nguyên được làm tròn xuống hoặc lên, tùy theo quy ước thư viện.
Viewport vs Bounding Box
Viewport là trạng thái camera. Bounding box là hình chữ nhật địa lý hiện đang hiển thị. Bạn tính bbox từ viewport mỗi khi bạn cần hỏi server "tôi nên hiển thị gì trong view này?".
Trong code:
const bbox = map.getBounds(); // trả về { _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());
Pattern này (tính bbox từ viewport, gửi lên server, render các feature được trả về) là nhịp tim của mọi trải nghiệm viewport-based search: bất động sản, listing, store locator, fleet tracking, ride-share.
Cách Viewport Điều Khiển Tải Tile
Khi viewport thay đổi, thư viện bản đồ tìm ra các tile nào bao phủ khu vực hiển thị mới ở mức zoom hiện tại, fetch các tile còn thiếu từ server (hoặc in-memory cache của nó), và render chúng. Tile đã được cache được tái sử dụng; tile ngoài viewport được giữ lại phòng trường hợp người dùng pan ngược lại.
Pan và zoom mượt mà cảm giác liền mạch vì thư viện đang làm công việc này bất đồng bộ: nó vẽ những gì nó có, fetch những gì nó cần, và cập nhật canvas khi tile mới đến. Các vector tile pipeline thực hiện thêm công việc render hình học thành pixel trên GPU, đó là lý do tại sao bản đồ web hiện đại sắc nét ở mọi zoom và góc xoay.
Lưu và Chia Sẻ Trạng Thái Viewport
Lưu viewport trong URL là pattern chuẩn cho các link bản đồ có thể chia sẻ. Hầu hết sản phẩm dùng URL hash như #map=14.5/52.5200/13.4050 (zoom, lat, lng). Khi tải trang, parse hash và apply viewport. Khi viewport thay đổi, debounce vài trăm millisecond và cập nhật hash để nút back của trình duyệt vẫn hoạt động hữu ích.
Với trạng thái nội bộ trình duyệt giữa các tab hoặc phiên, key localStorage với cùng hình dạng. Với các trang server-rendered, viewport thường xuất hiện dưới dạng query param cho URL SEO-friendly (?zoom=14&lat=52.52&lng=13.405).
Viewport Bias cho Search và Autocomplete
Geocoding API chấp nhận viewport (hoặc bbox của nó) như tham số bias. MapAtlas expose boundary.rect.* cho hard filter và focus.point.* cho soft bias. Không có bias, autocomplete cho "Springfield" trả về Springfield nào nổi tiếng nhất toàn cầu. Với viewport bias, người dùng gõ trong bản đồ Massachusetts của họ nhận được kết quả Massachusetts trước.
Apply bias này mỗi lần gõ phím. Chi phí chỉ là một tham số và gợi ý liên quan hơn đáng kể.
Viewport Ban Đầu: Bắt Đầu Ở Đâu
Điều đầu tiên mọi ứng dụng bản đồ phải quyết định là bắt đầu ở đâu. Các pattern phổ biến:
- Mặc định theo locale người dùng: người dùng ở Đức bắt đầu ở viewport trên Berlin, người dùng ở Pháp trên Paris.
- Mặc định theo viewport cuối của người dùng: duy trì viewport qua các phiên.
- Mặc định theo dữ liệu: nếu bản đồ của bạn hiển thị kết quả tìm kiếm, fit bbox của những kết quả đó khi render ban đầu.
- Mặc định theo IP geolocation của người dùng: độ chính xác thấp, không cần quyền, fallback tốt.
- Hỏi browser geolocation chỉ khi người dùng chọn rõ ràng: không bao giờ khi tải trang đầu tiên mà không có sự đồng ý UI.
Chọn viewport ban đầu hợp lý là chi tiết nhỏ với tác động lớn đến chất lượng cảm nhận.
MapAtlas Expose Trạng Thái Viewport Như Thế Nào
Component MapAtlas Dynamic Maps expose cùng API getCenter, getZoom, getBearing, getPitch và setView mà mọi bản đồ web cấp developer cung cấp, với bổ sung host chỉ tại EU và các tham số viewport bias nhất quán trên endpoint Geocoding và Search. Để tìm hiểu sâu hơn về cách viewport tương tác với tile và hình chiếu, xem Vector Tile là gì và Web Mercator là gì.
Câu hỏi thường gặp
Map viewport là gì?
Map viewport là cửa sổ hiển thị của bản đồ: khu vực địa lý hiện đang hiển thị trên màn hình, được mô tả bởi tọa độ trung tâm (vĩ độ và kinh độ), mức zoom (bản đồ được phóng to hay thu nhỏ bao nhiêu), và tùy chọn bearing (xoay) và pitch (nghiêng 3D). Mọi bản đồ web hiện đại (Google Maps, MapLibre, Mapbox GL, MapAtlas) expose viewport như state bạn có thể đọc và set theo chương trình. Viewport thay đổi mỗi khi người dùng pan, zoom, xoay hoặc nghiêng bản đồ.
Zoom level là gì?
Zoom level là số nguyên (hoặc thập phân) điều khiển lượng thế giới hiển thị trong tile có kích thước cố định. Zoom 0 vừa toàn bộ thế giới trong một tile 256x256. Mỗi mức zoom tiếp theo tăng gấp đôi độ phân giải: zoom 1 có 4 tile, zoom 2 có 16, và cứ thế. Zoom 14 xấp xỉ quy mô khu phố, zoom 18 xấp xỉ quy mô tòa nhà. Hầu hết bản đồ production hỗ trợ zoom từ 0 đến 22 hoặc hơn, mặc dù tile cơ bản chỉ tồn tại đến một mức zoom nhất định và được upsample hoặc up-resolve vượt qua đó.
Sự khác biệt giữa viewport và bounding box là gì?
Viewport là trạng thái camera (center, zoom, bearing, pitch). Bounding box là hình chữ nhật địa lý mà camera hiện đang hiển thị. Bạn tính bbox từ viewport: với center, zoom và kích thước màn hình đã cho, thư viện bản đồ tính toán hình chữ nhật lat/lng nào đang hiển thị. Bbox là thứ bạn truyền cho geocoding API như viewport bias, truy vấn cơ sở dữ liệu với các feature hiển thị, và log khi bạn muốn biết người dùng đang nhìn vào gì.
Làm thế nào để lưu và khôi phục map viewport?
Serialize bốn giá trị cốt lõi (vĩ độ trung tâm, kinh độ trung tâm, zoom, bearing nếu bạn hỗ trợ xoay) vào URL hoặc local storage. Một pattern phổ biến là hash như #map=14.5/52.5200/13.4050 cho zoom 14.5 tại trung tâm Berlin. Khi tải trang, parse hash và gọi map.setView(...) hoặc map.flyTo(...). MapAtlas, MapLibre và Mapbox GL đều expose API getCenter / getZoom / getBearing và setView tương đương, vì vậy round-trip này chỉ là một helper function trong bất kỳ codebase production nào.

