Người dùng có thể nghiêng và xoay bản đồ trong Maps SDK dành cho Android bằng các cử chỉ đơn giản, giúp họ điều chỉnh bản đồ theo hướng phù hợp. Ở bất kỳ mức thu phóng nào, bạn cũng có thể dịch chuyển bản đồ hoặc thay đổi góc nhìn của bản đồ với độ trễ rất thấp nhờ kích thước nhỏ hơn của các ô bản đồ dựa trên vectơ.
Mã mẫu
Kho lưu trữ ApiDemos trên GitHub có một mẫu minh hoạ các tính năng của camera:
- CameraDemoActivity – Kotlin: Thay đổi vị trí của camera
- CameraDemoActivity – Java: Thay đổi vị trí của camera
Giới thiệu
Giống như Google Maps trên web, Maps SDK cho Android thể hiện bề mặt của thế giới (một hình cầu) trên màn hình của thiết bị (một mặt phẳng) bằng cách sử dụng phép chiếu Mercator. Theo hướng đông và tây, bản đồ được lặp lại vô hạn vì thế giới tự bao quanh chính nó một cách liền mạch. Theo hướng bắc và nam, bản đồ bị giới hạn ở khoảng 85 độ bắc và 85 độ nam.
Lưu ý: Phép chiếu Mercator có chiều rộng hữu hạn theo chiều dọc nhưng chiều cao vô hạn theo chiều ngang. Chúng tôi "cắt" hình ảnh bản đồ cơ sở bằng phép chiếu Mercator ở khoảng +/- 85 độ để tạo ra hình dạng bản đồ vuông, giúp bạn dễ dàng chọn ô hơn.
SDK Bản đồ dành cho Android cho phép bạn thay đổi điểm nhìn của người dùng trên bản đồ bằng cách sửa đổi camera của bản đồ.
Những thay đổi đối với camera sẽ không ảnh hưởng đến các điểm đánh dấu, lớp phủ hoặc đồ hoạ khác mà bạn đã thêm, mặc dù bạn có thể muốn thay đổi những nội dung đã thêm để phù hợp hơn với chế độ xem mới.
Vì có thể lắng nghe cử chỉ của người dùng trên bản đồ, nên bạn có thể thay đổi bản đồ để phản hồi các yêu cầu của người dùng. Ví dụ: phương thức gọi lại OnMapClickListener.onMapClick()
phản hồi một thao tác nhấn duy nhất trên bản đồ. Vì phương thức này nhận được vĩ độ và kinh độ của vị trí nhấn, nên bạn có thể phản hồi bằng cách di chuyển hoặc thu phóng đến điểm đó.
Bạn có thể dùng các phương thức tương tự để phản hồi các thao tác nhấn vào bong bóng của điểm đánh dấu hoặc để phản hồi cử chỉ kéo trên điểm đánh dấu.
Bạn cũng có thể theo dõi chuyển động của camera để ứng dụng nhận được thông báo khi camera bắt đầu di chuyển, đang di chuyển hoặc dừng di chuyển. Để biết thông tin chi tiết, hãy xem hướng dẫn về các sự kiện thay đổi camera.
Vị trí camera
Chế độ xem bản đồ được mô phỏng như một camera nhìn xuống mặt phẳng. Vị trí của camera (và do đó, việc hiển thị bản đồ) được chỉ định bằng các thuộc tính sau: target (vị trí vĩ độ/kinh độ), bearing, tilt và zoom.
Mục tiêu (vị trí)
Mục tiêu của camera là vị trí ở tâm bản đồ, được chỉ định dưới dạng toạ độ vĩ độ và kinh độ.
Vĩ độ có thể nằm trong khoảng từ -85 đến 85 độ. Các giá trị cao hơn hoặc thấp hơn phạm vi này sẽ được xếp vào giá trị gần nhất trong phạm vi này. Ví dụ: nếu bạn chỉ định vĩ độ là 100, thì giá trị sẽ được đặt thành 85. Kinh độ nằm trong khoảng từ -180 đến 180 độ. Các giá trị nằm ngoài phạm vi này sẽ được bao bọc để nằm trong phạm vi (-180, 180). Ví dụ: 480, 840 và 1200 đều sẽ được chuyển thành 120 độ.Góc phương vị (hướng)
Hướng camera chỉ định hướng la bàn, được đo bằng độ so với hướng bắc thực, tương ứng với cạnh trên của bản đồ. Nếu bạn vẽ một đường thẳng đứng từ tâm bản đồ đến mép trên cùng của bản đồ, thì phương vị sẽ tương ứng với hướng của camera (được đo bằng độ) so với hướng bắc thực.
Góc phương vị 0 có nghĩa là phần trên cùng của bản đồ chỉ hướng bắc thực. Giá trị phương vị 90 có nghĩa là đỉnh của bản đồ chỉ về hướng đông (90 độ trên la bàn). Giá trị 180 có nghĩa là đỉnh của các điểm trên bản đồ hướng về phía nam.
Maps API cho phép bạn thay đổi hướng của bản đồ. Ví dụ: người lái xe thường xoay bản đồ đường bộ để căn chỉnh bản đồ theo hướng di chuyển của họ, trong khi người đi bộ đường dài sử dụng bản đồ và la bàn thường định hướng bản đồ sao cho một đường thẳng đứng chỉ về hướng bắc.
Độ nghiêng (góc nhìn)
Độ nghiêng xác định vị trí của camera trên một vòng cung ngay trên vị trí trung tâm của bản đồ, được đo bằng độ từ điểm thiên để (hướng chỉ thẳng xuống dưới camera). Giá trị 0 tương ứng với một camera hướng thẳng xuống. Giá trị lớn hơn 0 tương ứng với một camera được nghiêng về phía đường chân trời theo số độ đã chỉ định. Khi bạn thay đổi góc nhìn, bản đồ sẽ xuất hiện ở chế độ phối cảnh, với các đối tượng ở xa xuất hiện nhỏ hơn và các đối tượng ở gần xuất hiện lớn hơn. Các hình minh hoạ sau đây sẽ minh hoạ điều này.
Trong các hình ảnh bên dưới, góc nhìn là 0 độ. Hình ảnh đầu tiên cho thấy sơ đồ của việc này; vị trí 1 là vị trí của camera và vị trí 2 là vị trí hiện tại trên bản đồ. Bản đồ kết quả xuất hiện bên dưới.
|
|
Trong các hình ảnh bên dưới, góc nhìn là 45 độ. Lưu ý rằng camera di chuyển nửa chừng dọc theo một vòng cung giữa vị trí thẳng đứng (0 độ) và mặt đất (90 độ), đến vị trí 3. Camera vẫn hướng vào điểm trung tâm của bản đồ, nhưng giờ đây, bạn có thể thấy khu vực do đường thẳng ở vị trí 4 biểu thị.
|
|
Bản đồ trong ảnh chụp màn hình này vẫn được căn giữa tại cùng một điểm như trong bản đồ ban đầu, nhưng có nhiều đối tượng hơn xuất hiện ở đầu bản đồ. Khi bạn tăng góc lên quá 45 độ, các đối tượng giữa camera và vị trí trên bản đồ sẽ xuất hiện lớn hơn theo tỷ lệ, trong khi các đối tượng ngoài vị trí trên bản đồ sẽ xuất hiện nhỏ hơn theo tỷ lệ, tạo ra hiệu ứng ba chiều.
Zoom (thu phóng)
Mức thu phóng của camera sẽ xác định tỷ lệ của bản đồ. Ở mức thu phóng lớn hơn, bạn có thể thấy nhiều chi tiết hơn trên màn hình, trong khi ở mức thu phóng nhỏ hơn, bạn có thể thấy nhiều phần hơn trên thế giới trên màn hình. Ở mức thu phóng 0, tỷ lệ của bản đồ là toàn bộ thế giới có chiều rộng khoảng 256 dp (pixel không phụ thuộc vào mật độ).
Việc tăng mức thu phóng thêm 1 sẽ tăng gấp đôi chiều rộng của thế giới trên màn hình. Do đó, ở mức thu phóng N, chiều rộng của thế giới xấp xỉ 256 * 2N dp. Ví dụ: ở mức thu phóng 2, toàn bộ thế giới có chiều rộng khoảng 1024 dp.
Cấp độ thu phóng không cần phải là số nguyên. Phạm vi mức thu phóng mà bản đồ cho phép phụ thuộc vào một số yếu tố, bao gồm cả mục tiêu, loại bản đồ và kích thước màn hình. Mọi số nằm ngoài phạm vi sẽ được chuyển đổi thành giá trị hợp lệ gần nhất tiếp theo, có thể là mức thu phóng tối thiểu hoặc mức thu phóng tối đa. Danh sách sau đây cho biết mức độ chi tiết gần đúng mà bạn có thể thấy ở từng mức thu phóng:
- 1: Thế giới
- 5: Khối đất/lục địa
- 10: Thành phố
- 15: Đường phố
- 20: Toà nhà
|
|
|
Di chuyển camera
Maps API cho phép bạn thay đổi phần nào của thế giới xuất hiện trên bản đồ. Việc này được thực hiện bằng cách thay đổi vị trí của camera (thay vì di chuyển bản đồ).
Khi thay đổi camera, bạn có thể chọn tạo hiệu ứng chuyển động cho camera kết quả. Ảnh động sẽ nội suy giữa các thuộc tính camera hiện tại và các thuộc tính camera mới. Bạn cũng có thể kiểm soát thời lượng của ảnh động.
Để thay đổi vị trí của camera, bạn phải chỉ định vị trí mà bạn muốn di chuyển camera bằng cách sử dụng CameraUpdate
. Maps API cho phép bạn tạo nhiều loại CameraUpdate
bằng cách sử dụng CameraUpdateFactory
. Bạn có các tuỳ chọn sau đây:
Thay đổi mức thu phóng và đặt mức thu phóng tối thiểu/tối đa
CameraUpdateFactory.zoomIn()
và CameraUpdateFactory.zoomOut()
cung cấp cho bạn một CameraUpdate
thay đổi mức thu phóng theo 1.0, trong khi vẫn giữ nguyên tất cả các thuộc tính khác.
CameraUpdateFactory.zoomTo(float)
cung cấp cho bạn một CameraUpdate
giúp thay đổi mức thu phóng thành giá trị đã cho, trong khi vẫn giữ nguyên tất cả các thuộc tính khác.
CameraUpdateFactory.zoomBy(float)
và CameraUpdateFactory.zoomBy(float, Point)
cho bạn một CameraUpdate
làm tăng (hoặc giảm, nếu giá trị là âm) mức thu phóng theo giá trị đã cho. Lựa chọn sau sẽ cố định điểm đã cho trên màn hình để điểm đó vẫn ở cùng một vị trí (vĩ độ/kinh độ) và do đó, lựa chọn này có thể thay đổi vị trí của camera để đạt được mục tiêu này.
Bạn có thể thấy việc đặt mức thu phóng tối thiểu và/hoặc tối đa ưu tiên là hữu ích. Ví dụ: điều này rất hữu ích để kiểm soát trải nghiệm của người dùng nếu ứng dụng của bạn cho thấy một khu vực xác định xung quanh một địa điểm yêu thích hoặc nếu bạn đang sử dụng lớp phủ ô tuỳ chỉnh với một số ít mức thu phóng.
Kotlin
private lateinit var map: GoogleMap map.setMinZoomPreference(6.0f) map.setMaxZoomPreference(14.0f)
Java
private GoogleMap map; map.setMinZoomPreference(6.0f); map.setMaxZoomPreference(14.0f);
Xin lưu ý rằng có những yếu tố kỹ thuật có thể ngăn API cho phép người dùng thu phóng quá thấp hoặc quá cao. Ví dụ: vệ tinh hoặc địa hình có thể có mức thu phóng tối đa thấp hơn so với các ô bản đồ cơ sở.
Thay đổi vị trí của camera
Có hai phương thức thuận tiện cho các thay đổi vị trí phổ biến.
CameraUpdateFactory.newLatLng(LatLng)
cung cấp cho bạn một CameraUpdate
giúp thay đổi vĩ độ và kinh độ của camera, đồng thời giữ nguyên tất cả các thuộc tính khác.
CameraUpdateFactory.newLatLngZoom(LatLng, float)
cung cấp cho bạn một CameraUpdate
giúp thay đổi vĩ độ, kinh độ và mức thu phóng của camera, đồng thời giữ nguyên tất cả các thuộc tính khác.
Để có thể thay đổi vị trí camera một cách linh hoạt, hãy dùng CameraUpdateFactory.newCameraPosition(CameraPosition)
. Lệnh này sẽ cung cấp cho bạn một CameraUpdate
để di chuyển camera đến vị trí đã cho. Bạn có thể nhận CameraPosition
trực tiếp bằng cách dùng new CameraPosition()
hoặc bằng CameraPosition.Builder
bằng cách dùng new CameraPosition.Builder()
.
Di chuyển (cuộn)
CameraUpdateFactory.scrollBy(float, float)
cung cấp cho bạn một CameraUpdate
giúp thay đổi vĩ độ và kinh độ của camera để bản đồ di chuyển theo số lượng pixel được chỉ định. Giá trị x dương khiến camera di chuyển sang phải, do đó bản đồ có vẻ như đã di chuyển sang trái. Giá trị y dương khiến camera di chuyển xuống, do đó bản đồ có vẻ như đã di chuyển lên. Ngược lại, các giá trị x âm khiến camera di chuyển sang trái, do đó, bản đồ có vẻ như đã di chuyển sang phải và các giá trị y âm khiến camera di chuyển lên trên. Thao tác di chuyển tương ứng với hướng hiện tại của camera. Ví dụ: nếu camera có phương vị là 90 độ, thì hướng đông là "lên".
Đặt ra ranh giới
Đặt ranh giới của bản đồ
Đôi khi, bạn nên di chuyển camera sao cho toàn bộ khu vực mà bạn quan tâm đều xuất hiện ở mức thu phóng lớn nhất có thể. Ví dụ: nếu đang hiển thị tất cả các trạm xăng trong phạm vi 5 dặm tính từ vị trí hiện tại của người dùng, bạn có thể muốn di chuyển camera sao cho tất cả các trạm xăng đều xuất hiện trên màn hình. Để làm việc này, trước tiên, hãy tính toán LatLngBounds
mà bạn muốn hiển thị trên màn hình. Sau đó, bạn có thể dùng CameraUpdateFactory.newLatLngBounds(LatLngBounds bounds, int
padding)
để lấy một CameraUpdate
thay đổi vị trí camera sao cho LatLngBounds
đã cho hoàn toàn nằm trong bản đồ, có tính đến khoảng đệm (tính bằng pixel) được chỉ định. CameraUpdate
được trả về đảm bảo rằng khoảng cách (tính bằng pixel) giữa các ranh giới đã cho và cạnh của bản đồ sẽ ít nhất bằng khoảng đệm đã chỉ định. Xin lưu ý rằng độ nghiêng và hướng của bản đồ sẽ đều là 0.
Kotlin
val australiaBounds = LatLngBounds( LatLng((-44.0), 113.0), // SW bounds LatLng((-10.0), 154.0) // NE bounds ) map.moveCamera(CameraUpdateFactory.newLatLngBounds(australiaBounds, 0))
Java
LatLngBounds australiaBounds = new LatLngBounds( new LatLng(-44, 113), // SW bounds new LatLng(-10, 154) // NE bounds ); map.moveCamera(CameraUpdateFactory.newLatLngBounds(australiaBounds, 0));
Đặt bản đồ vào giữa một khu vực
Trong một số trường hợp, bạn có thể muốn đặt camera ở giữa trong một ranh giới thay vì bao gồm cả các đường viền ngoài cùng. Ví dụ: để đặt camera ở giữa một quốc gia trong khi vẫn duy trì mức thu phóng không đổi. Trong trường hợp này, bạn có thể sử dụng một phương thức tương tự bằng cách tạo LatLngBounds
và sử dụng CameraUpdateFactory.newLatLngZoom(LatLng latLng, float zoom)
với LatLngBounds
.Phương thức getCenter()
. Phương thức getCenter() sẽ trả về tâm địa lý của LatLngBounds
.
Kotlin
val australiaBounds = LatLngBounds( LatLng((-44.0), 113.0), // SW bounds LatLng((-10.0), 154.0) // NE bounds ) map.moveCamera(CameraUpdateFactory.newLatLngZoom(australiaBounds.center, 10f))
Java
LatLngBounds australiaBounds = new LatLngBounds( new LatLng(-44, 113), // SW bounds new LatLng(-10, 154) // NE bounds ); map.moveCamera(CameraUpdateFactory.newLatLngZoom(australiaBounds.getCenter(), 10));
Một phương thức nạp chồng, newLatLngBounds(boundary, width, height,
padding)
cho phép bạn chỉ định chiều rộng và chiều cao tính bằng pixel cho một hình chữ nhật, với mục đích là các kích thước này tương ứng với kích thước của bản đồ. Hình chữ nhật được định vị sao cho tâm của hình chữ nhật giống với tâm của khung hiển thị bản đồ (để nếu các phương diện được chỉ định giống với các phương diện của khung hiển thị bản đồ, thì hình chữ nhật sẽ trùng với khung hiển thị bản đồ). CameraUpdate
được trả về sẽ di chuyển camera sao cho LatLngBounds
đã chỉ định nằm ở giữa màn hình trong hình chữ nhật đã cho ở mức thu phóng lớn nhất có thể, có tính đến khoảng đệm cần thiết.
Lưu ý: Chỉ sử dụng phương thức đơn giản hơn newLatLngBounds(boundary, padding)
để tạo CameraUpdate
nếu bạn sẽ dùng phương thức này để di chuyển camera sau khi bản đồ đã trải qua bố cục. Trong quá trình bố trí, API sẽ tính toán ranh giới hiển thị của bản đồ cần thiết để chiếu chính xác hộp giới hạn. Để so sánh, bạn có thể sử dụng CameraUpdate
do phương thức phức tạp hơn newLatLngBounds(boundary, width, height, padding)
trả về bất cứ lúc nào, ngay cả trước khi bản đồ trải qua bố cục, vì API này tính toán ranh giới hiển thị từ các đối số mà bạn truyền.
Hạn chế thao tác xoay của người dùng trong một khu vực nhất định
Trong các trường hợp trên, bạn đặt ranh giới cho bản đồ nhưng sau đó người dùng có thể cuộn hoặc di chuyển bên ngoài các ranh giới này. Thay vào đó, bạn có thể muốn hạn chế ranh giới tâm vĩ độ/kinh độ của tiêu điểm trên bản đồ (mục tiêu của camera) để người dùng chỉ có thể cuộn và di chuyển trong những ranh giới này. Ví dụ: một ứng dụng bán lẻ cho trung tâm mua sắm hoặc sân bay có thể muốn giới hạn bản đồ trong một ranh giới cụ thể, cho phép người dùng cuộn và di chuyển trong ranh giới đó.
Kotlin
// Create a LatLngBounds that includes the city of Adelaide in Australia. val adelaideBounds = LatLngBounds( LatLng(-35.0, 138.58), // SW bounds LatLng(-34.9, 138.61) // NE bounds ) // Constrain the camera target to the Adelaide bounds. map.setLatLngBoundsForCameraTarget(adelaideBounds)
Java
// Create a LatLngBounds that includes the city of Adelaide in Australia. LatLngBounds adelaideBounds = new LatLngBounds( new LatLng(-35.0, 138.58), // SW bounds new LatLng(-34.9, 138.61) // NE bounds ); // Constrain the camera target to the Adelaide bounds. map.setLatLngBoundsForCameraTarget(adelaideBounds);
Sơ đồ sau đây minh hoạ một trường hợp khi đích của camera bị giới hạn trong một khu vực lớn hơn một chút so với khung hiển thị. Người dùng có thể cuộn và xoay, miễn là mục tiêu của camera vẫn nằm trong khu vực có ranh giới. Dấu thập biểu thị mục tiêu của camera:
Bản đồ luôn lấp đầy khung nhìn, ngay cả khi điều đó dẫn đến việc khung nhìn hiển thị các khu vực nằm ngoài ranh giới đã xác định. Ví dụ: nếu bạn đặt mục tiêu camera ở một góc của khu vực có ranh giới, thì khu vực bên ngoài góc đó sẽ xuất hiện trong khung hiển thị nhưng người dùng không thể cuộn thêm vào khu vực đó. Sơ đồ sau đây minh hoạ tình huống này. Dấu thập biểu thị mục tiêu của camera:
Trong sơ đồ sau, mục tiêu của camera có ranh giới rất hạn chế, khiến người dùng có rất ít cơ hội để cuộn hoặc xoay bản đồ. Dấu thập này đại diện cho mục tiêu của camera:
Đang cập nhật chế độ xem camera
Để áp dụng CameraUpdate
cho bản đồ, bạn có thể di chuyển camera ngay lập tức hoặc tạo hiệu ứng chuyển động mượt mà cho camera. Để di chuyển camera ngay lập tức bằng CameraUpdate
đã cho, bạn có thể gọi GoogleMap.moveCamera(CameraUpdate)
.
Bạn có thể cải thiện trải nghiệm người dùng, đặc biệt là đối với các bước di chuyển ngắn, bằng cách tạo hiệu ứng cho thay đổi. Để thực hiện việc này, thay vì gọi GoogleMap.moveCamera
, hãy gọi GoogleMap.animateCamera
.
Bản đồ sẽ di chuyển mượt mà đến các thuộc tính mới. Dạng chi tiết nhất của phương thức này, GoogleMap.animateCamera(cameraUpdate, duration, callback)
, cung cấp 3 đối số:
cameraUpdate
CameraUpdate
mô tả vị trí cần di chuyển camera.callback
- Một đối tượng triển khai
GoogleMap.CancellableCallback
. Giao diện chung này để xử lý các tác vụ xác định hai phương thức "onCancel()" và "onFinished()". Đối với ảnh động, các phương thức này được gọi trong các trường hợp sau:onFinish()
- Được gọi nếu ảnh động hoàn tất mà không bị gián đoạn.
onCancel()
-
Được gọi nếu ảnh động bị gián đoạn bằng cách gọi
stopAnimation()
hoặc bắt đầu một chuyển động camera mới.Ngoài ra, lỗi này cũng có thể xảy ra nếu bạn gọi
GoogleMap.stopAnimation()
.
duration
- Thời lượng mong muốn của ảnh động, tính bằng mili giây, dưới dạng
int
.
Các đoạn mã sau đây minh hoạ một số cách phổ biến để di chuyển camera.
Kotlin
val sydney = LatLng(-33.88, 151.21) val mountainView = LatLng(37.4, -122.1) // Move the camera instantly to Sydney with a zoom of 15. map.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 15f)) // Zoom in, animating the camera. map.animateCamera(CameraUpdateFactory.zoomIn()) // Zoom out to zoom level 10, animating with a duration of 2 seconds. map.animateCamera(CameraUpdateFactory.zoomTo(10f), 2000, null) // Construct a CameraPosition focusing on Mountain View and animate the camera to that position. val cameraPosition = CameraPosition.Builder() .target(mountainView) // Sets the center of the map to Mountain View .zoom(17f) // Sets the zoom .bearing(90f) // Sets the orientation of the camera to east .tilt(30f) // Sets the tilt of the camera to 30 degrees .build() // Creates a CameraPosition from the builder map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
Java
LatLng sydney = new LatLng(-33.88,151.21); LatLng mountainView = new LatLng(37.4, -122.1); // Move the camera instantly to Sydney with a zoom of 15. map.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 15)); // Zoom in, animating the camera. map.animateCamera(CameraUpdateFactory.zoomIn()); // Zoom out to zoom level 10, animating with a duration of 2 seconds. map.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null); // Construct a CameraPosition focusing on Mountain View and animate the camera to that position. CameraPosition cameraPosition = new CameraPosition.Builder() .target(mountainView ) // Sets the center of the map to Mountain View .zoom(17) // Sets the zoom .bearing(90) // Sets the orientation of the camera to east .tilt(30) // Sets the tilt of the camera to 30 degrees .build(); // Creates a CameraPosition from the builder map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));