Tài liệu này thảo luận về các loại bản đồ mà bạn có thể hiển thị bằng cách sử dụng
API JavaScript cho Maps. API này sử dụng một MapType
để lưu trữ thông tin về các bản đồ này. Một MapType
là giao diện xác định cách hiển thị và sử dụng các ô bản đồ và
bản dịch hệ toạ độ từ toạ độ màn hình sang hệ toạ độ thế giới
toạ độ (trên bản đồ). Mỗi MapType
phải chứa một
một vài phương pháp để xử lý việc truy xuất và giải phóng thẻ thông tin cũng như thuộc tính
xác định hoạt động trực quan của lớp đó.
Hoạt động bên trong của các loại bản đồ trong API JavaScript của Maps là một chủ đề nâng cao. Hầu hết các nhà phát triển đều có thể sử dụng các loại bản đồ cơ bản như sau. Tuy nhiên, bạn cũng có thể sửa đổi cách trình bày các loại bản đồ hiện có bằng cách sử dụng Bản đồ được tạo kiểu hoặc xác định các ô bản đồ của riêng bạn bằng cách sử dụng các loại bản đồ tuỳ chỉnh. Khi cung cấp các loại bản đồ tuỳ chỉnh, bạn sẽ cần phải hiểu cách sửa đổi Sổ đăng ký loại bản đồ.
Các loại bản đồ cơ bản
Có bốn loại bản đồ có sẵn trong API JavaScript của Maps. Ngoài hình ảnh "vẽ" quen thuộc ô bản đồ đường đi, API JavaScript của Maps cũng hỗ trợ các loại bản đồ khác.
Các loại bản đồ sau đây có sẵn trong API JavaScript của Maps:
roadmap
cho thấy chế độ xem bản đồ đường mặc định. Chiến dịch này là loại bản đồ mặc định.satellite
hiển thị vệ tinh Google Earth hình ảnh.hybrid
hiển thị kết hợp giữa thông thường và vệ tinh lượt xem.terrain
hiển thị bản đồ thực dựa trên địa hình của bạn.
Bạn sửa đổi loại bản đồ mà Map
sử dụng bằng cách đặt
Thuộc tính mapTypeId
, trong hàm khởi tạo thông qua chế độ cài đặt
đối tượng Map options
của mình hoặc bằng cách gọi thuộc tính
setMapTypeId()
. Thuộc tính mapTypeID
mặc định là roadmap
.
Đặt mapTypeId
trong quá trình tạo:
var myLatlng = new google.maps.LatLng(-34.397, 150.644); var mapOptions = { zoom: 8, center: myLatlng, mapTypeId: 'satellite' }; var map = new google.maps.Map(document.getElementById('map'), mapOptions);
Sửa đổi mapTypeId
một cách linh động:
map.setMapTypeId('terrain');
Lưu ý rằng bạn không thực sự trực tiếp đặt loại bản đồ của bản đồ,
nhưng thay vào đó, đặt mapTypeId
để tham chiếu đến một
MapType
bằng một giá trị nhận dạng.
API JavaScript của Maps sử dụng sổ đăng ký loại bản đồ,
được giải thích bên dưới, để quản lý các tham chiếu này.
Hình ảnh 45°
API JavaScript của Maps hỗ trợ hình ảnh 45° đặc biệt cho các vị trí nhất định. Hình ảnh có độ phân giải cao này cung cấp phối cảnh theo từng hướng chính (Bắc, Nam, Đông, Tây). Những hình ảnh này có sẵn tại mức thu phóng cho loại bản đồ được hỗ trợ.
Hình ảnh sau đây hiển thị chế độ xem 45° của Thành phố New York:
Loại bản đồ satellite
và hybrid
hỗ trợ 45°
hình ảnh ở mức thu phóng cao (từ 12 trở lên) nếu có. Nếu người dùng
phóng to một vị trí mà hình ảnh đó tồn tại, các loại bản đồ này
tự động thay đổi quan điểm của mình theo cách sau:
- Hình ảnh vệ tinh hoặc hình ảnh kết hợp được thay thế bằng hình ảnh cung cấp góc nhìn 45°
, căn giữa vào vị trí hiện tại. Theo mặc định, những chế độ xem đó
có hướng bắc. Nếu người dùng thu nhỏ, vệ tinh mặc định hoặc
hình ảnh kết hợp lại xuất hiện. Hành vi này sẽ khác nhau tuỳ thuộc vào mức độ thu phóng
và giá trị của
tilt
: - Giữa các mức thu phóng 12 và 18, bản đồ cơ sở từ trên xuống (0°) hiển thị theo
trừ phi bạn đặt
tilt
thành 45. - Ở mức thu phóng 18 trở lên, bản đồ cơ sở 45° sẽ hiển thị trừ khi
tilt
được đặt thành 0. - Nút điều khiển xoay sẽ hiển thị. Nút điều khiển xoay cung cấp các tuỳ chọn
cho phép người dùng bật/tắt độ nghiêng và xoay chế độ xem một góc 90°
tăng dần theo một trong hai hướng. Để ẩn nút điều khiển xoay, hãy đặt
rotateControl
thànhfalse
.
Thu nhỏ từ một loại bản đồ hiển thị hình ảnh 45° sẽ bị huỷ bỏ mỗi thay đổi trong số này, tái thiết lập các kiểu bản đồ ban đầu.
Bật và tắt hình ảnh 45°
Bạn có thể tắt hình ảnh 45° bằng cách gọi setTilt(0)
trên
Đối tượng Map
. Để bật hình ảnh 45° cho các loại bản đồ được hỗ trợ,
gọi setTilt(45)
. getTilt()
của Map
sẽ luôn phản ánh tilt
hiện tại được hiển thị trên
ánh xạ; nếu bạn đặt tilt
trên bản đồ rồi sau đó xoá giá trị đó
tilt
(ví dụ: bằng cách thu nhỏ bản đồ),
Phương thức getTilt()
sẽ trả về 0
.
Lưu ý quan trọng: Hình ảnh 45° chỉ được hỗ trợ trên bản đồ raster; không thể sử dụng hình ảnh này với bản đồ vectơ.
Ví dụ sau đây hiển thị chế độ xem 45° của Thành phố New York:
TypeScript
function initMap(): void { const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { center: { lat: 40.76, lng: -73.983 }, zoom: 15, mapTypeId: "satellite", } ); map.setTilt(45); } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
function initMap() { const map = new google.maps.Map(document.getElementById("map"), { center: { lat: 40.76, lng: -73.983 }, zoom: 15, mapTypeId: "satellite", }); map.setTilt(45); } window.initMap = initMap;
Dùng thử mẫu
Xoay hình ảnh 45°
Hình ảnh 45° thực tế bao gồm một tập hợp hình ảnh
cho từng hướng chính (Bắc, Nam, Đông, Tây). Sau khi bản đồ của bạn
đang hiển thị hình ảnh 45°, bạn có thể định hướng
hình ảnh về một trong các hướng chính bằng cách gọi
setHeading()
trên đối tượng Map
, truyền
một giá trị số được biểu thị bằng độ từ Bắc.
Ví dụ sau đây minh hoạ bản đồ trên không và các chế độ tự động xoay bản đồ 3 giây một lần khi nút được nhấp vào:
TypeScript
let map: google.maps.Map; function initMap(): void { map = new google.maps.Map(document.getElementById("map") as HTMLElement, { center: { lat: 40.76, lng: -73.983 }, zoom: 15, mapTypeId: "satellite", heading: 90, tilt: 45, }); // add listener to button document.getElementById("rotate")!.addEventListener("click", autoRotate); } function rotate90(): void { const heading = map.getHeading() || 0; map.setHeading(heading + 90); } function autoRotate(): void { // Determine if we're showing aerial imagery. if (map.getTilt() !== 0) { window.setInterval(rotate90, 3000); } } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
let map; function initMap() { map = new google.maps.Map(document.getElementById("map"), { center: { lat: 40.76, lng: -73.983 }, zoom: 15, mapTypeId: "satellite", heading: 90, tilt: 45, }); // add listener to button document.getElementById("rotate").addEventListener("click", autoRotate); } function rotate90() { const heading = map.getHeading() || 0; map.setHeading(heading + 90); } function autoRotate() { // Determine if we're showing aerial imagery. if (map.getTilt() !== 0) { window.setInterval(rotate90, 3000); } } window.initMap = initMap;
Dùng thử mẫu
Sửa đổi Sổ đăng ký kiểu bản đồ
mapTypeId
của bản đồ là một giá trị nhận dạng chuỗi
dùng để liên kết MapType
với một
giá trị duy nhất. Mỗi đối tượng Map
duy trì một
MapTypeRegistry
chứa tập hợp
MapType
có sẵn cho bản đồ đó. Sổ đăng ký này
được dùng để chọn loại bản đồ có sẵn trong
ví dụ: điều khiển MapType của Map.
Bạn không đọc trực tiếp từ sổ đăng ký loại bản đồ. Thay vào đó,
bạn sửa đổi sổ đăng ký bằng cách thêm các loại bản đồ tùy chỉnh và liên kết
bằng một chuỗi giá trị nhận dạng do bạn chọn. Bạn không thể sửa đổi
hoặc thay đổi loại bản đồ cơ bản (mặc dù bạn có thể xoá chúng khỏi
bằng cách thay đổi giao diện của các liên kết
mapTypeControlOptions
).
Mã sau đây đặt bản đồ để chỉ hiển thị
hai loại bản đồ trong mapTypeControlOptions
của bản đồ
và sửa đổi sổ đăng ký để thêm mối liên kết với
mã nhận dạng này vào quy trình triển khai
Giao diện MapType
.
// Modify the control to only display two maptypes, the // default ROADMAP and the custom 'mymap'. // Note that because this is an association, we // don't need to modify the MapTypeRegistry beforehand. var MY_MAPTYPE_ID = 'mymaps'; var mapOptions = { zoom: 12, center: brooklyn, mapTypeControlOptions: { mapTypeIds: ['roadmap', MY_MAPTYPE_ID] }, mapTypeId: MY_MAPTYPE_ID }; // Create our map. This creation will implicitly create a // map type registry. map = new google.maps.Map(document.getElementById('map'), mapOptions); // Create your custom map type using your own code. // (See below.) var myMapType = new MyMapType(); // Set the registry to associate 'mymap' with the // custom map type we created, and set the map to // show that map type. map.mapTypes.set(MY_MAPTYPE_ID, myMapType);
Bản đồ được tạo mẫu
StyledMapType
cho phép bạn tuỳ chỉnh bản trình bày của
bản đồ cơ sở tiêu chuẩn của Google, thay đổi cách hiển thị trực quan của các phần tử đó
như các con đường, công viên và các khu vực được xây dựng để thể hiện một phong cách khác với
được sử dụng trong loại bản đồ mặc định.
Để biết thêm thông tin về StyledMapType
, hãy xem hướng dẫn về
bản đồ được tạo kiểu.
Các loại bản đồ tùy chỉnh
API JavaScript của Maps hỗ trợ màn hình và quản lý các loại bản đồ tuỳ chỉnh, cho phép bạn triển khai hình ảnh bản đồ hoặc lớp phủ ô của riêng bạn.
Có thể có một số cách triển khai loại bản đồ trong API Maps JavaScript:
- Bộ ô chuẩn bao gồm các hình ảnh mà
tạo thành các bản đồ bản đồ đầy đủ. Ô này
nhóm còn được gọi là loại bản đồ cơ sở. Các loại bản đồ này
hành động và hoạt động giống như các loại bản đồ mặc định hiện có:
roadmap
,satellite
hybrid
vàterrain
. Bạn có thể thêm loại bản đồ tuỳ chỉnh cho mảngmapTypes
của Map đến cho phép giao diện người dùng trong API JavaScript của Maps coi loại bản đồ tuỳ chỉnh của bạn là loại bản đồ tiêu chuẩn (bằng cách đưa nó vào MapType kiểm soát). - Lớp phủ ô hình ảnh hiển thị ở đầu loại bản đồ cơ sở hiện có. Nhìn chung, các loại bản đồ này được dùng để bổ sung loại bản đồ hiện có nhằm hiển thị thông tin và thường bị hạn chế ở các vị trí cụ thể và/hoặc mức thu phóng. Lưu ý rằng các ô này có thể trong suốt, cho phép bạn thêm các đối tượng địa lý vào bản đồ hiện có.
- Các loại bản đồ không phải là hình ảnh, cho phép bạn thao tác việc hiển thị thông tin bản đồ ở mức cơ bản nhất.
Mỗi phương án này dựa trên việc tạo một lớp
triển khai MapType
. Ngoài ra,
Lớp ImageMapType
cung cấp một số tính năng tích hợp sẵn
để đơn giản hoá việc tạo các loại bản đồ hình ảnh.
Giao diện MapType
Trước khi bạn tạo các lớp triển khai MapType
,
điều quan trọng là phải hiểu cách Google Maps xác định
toạ độ và quyết định phần nào của bản đồ sẽ hiển thị. Bạn cần
triển khai logic tương tự cho mọi loại bản đồ cơ sở hoặc bản đồ lớp phủ.
Đọc hướng dẫn lập bản đồ
và toạ độ ô.
Các loại bản đồ tuỳ chỉnh phải triển khai MapType
. Giao diện này chỉ định một số thuộc tính và
các phương thức cho phép API bắt đầu yêu cầu đối với bản đồ của bạn
(các) loại khi API xác định cần hiển thị bản đồ
ô trong chế độ xem và mức thu phóng hiện tại. Bạn xử lý
các yêu cầu này để quyết định thẻ thông tin nào cần tải.
Lưu ý: Bạn có thể tạo
riêng để triển khai giao diện này. Ngoài ra, nếu bạn có
Bạn có thể sử dụng
Lớp ImageMapType
đã triển khai
giao diện này.
Các lớp triển khai giao diện MapType
yêu cầu bạn xác định và điền sẵn các thuộc tính sau:
tileSize
(bắt buộc) chỉ định kích thước của ô (thuộc loạigoogle.maps.Size
). Kích thước phải là hình chữ nhật nhưng không cần phải là hình vuông.maxZoom
(bắt buộc) chỉ định mức thu phóng tối đa cấp hiển thị ô của loại bản đồ này.minZoom
(không bắt buộc) chỉ định mức thu phóng tối thiểu cấp độ để hiển thị ô của loại bản đồ này. Theo mặc định, giá trị này là0
cho biết rằng không có giá trị tối thiểu nào mức thu phóng đã tồn tại.name
(không bắt buộc) chỉ định tên cho bản đồ này loại. Thuộc tính này chỉ cần thiết nếu bạn muốn loại bản đồ này có thể chọn trong chế độ kiểm soát MapType. (Xem Đang thêm chế độ điều khiểnMapType
ở bên dưới.)alt
(không bắt buộc) chỉ định văn bản thay thế cho thuộc tính này loại bản đồ, được thể hiện dưới dạng văn bản khi di chuột. Thuộc tính này chỉ cần thiết nếu bạn muốn loại bản đồ này có thể chọn được trong chế độ kiểm soát MapType. (Xem phần ThêmMapType
chế độ điều khiển below.)
Ngoài ra, các lớp triển khai giao diện MapType
cần triển khai các phương thức sau:
-
getTile()
(bắt buộc) được gọi bất cứ khi nào API xác định rằng bản đồ cần hiển thị các ô mới cho khung nhìn. Phương thứcgetTile()
phải có các phần tử sau chữ ký:getTile(tileCoord:Point,zoom:number,ownerDocument:Document):Node
API xác định xem có cần gọi
getTile()
hay không dựa trêntileSize
củaMapType
,minZoom
vàmaxZoom
các thuộc tính cũng như chế độ xem và mức thu phóng hiện tại của bản đồ. Trình xử lý cho phương thức này sẽ trả về phần tử HTML với toạ độ đã được thông qua, mức thu phóng và phần tử DOM để nối hình ảnh xếp kề. -
releaseTile()
(không bắt buộc) được gọi bất cứ khi nào API xác định rằng bản đồ cần phải xoá thẻ thông tin khi thẻ thông tin nằm ngoài chế độ xem. Phương thức này phải có chữ ký sau:releaseTile(tile:Node)
Thông thường, bạn cần xử lý việc xoá mọi phần tử được gắn vào các ô bản đồ khi thêm vào bản đồ. Ví dụ: nếu bạn đã đính kèm trình nghe sự kiện vào thẻ thông tin ánh xạ bạn nên xoá chúng tại đây.
Phương thức getTile()
đóng vai trò là bộ điều khiển chính đối với
xác định thẻ thông tin nào sẽ tải trong một khung nhìn nhất định.
Các loại bản đồ cơ sở
Loại bản đồ mà bạn xây dựng theo cách này có thể
một mình hoặc kết hợp với các loại bản đồ khác làm lớp phủ. Quảng cáo độc lập
loại bản đồ được gọi là loại bản đồ cơ sở. Bạn có thể muốn có API
xử lý các MapType
tuỳ chỉnh đó giống như với bất kỳ miền hiện có nào khác
loại bản đồ cơ sở (ROADMAP
, TERRAIN
, v.v.). Việc cần làm
Vì vậy, hãy thêm MapType
tuỳ chỉnh của bạn vào Map
thuộc tính mapTypes
. Thuộc tính này thuộc loại
MapTypeRegistry
.
Đoạn mã sau đây tạo một MapType
cơ sở để hiển thị
toạ độ ô của bản đồ và vẽ đường viền của ô:
TypeScript
/* * This demo demonstrates how to replace default map tiles with custom imagery. * In this case, the CoordMapType displays gray tiles annotated with the tile * coordinates. * * Try panning and zooming the map to see how the coordinates change. */ class CoordMapType { tileSize: google.maps.Size; maxZoom = 19; name = "Tile #s"; alt = "Tile Coordinate Map Type"; constructor(tileSize: google.maps.Size) { this.tileSize = tileSize; } getTile( coord: google.maps.Point, zoom: number, ownerDocument: Document ): HTMLElement { const div = ownerDocument.createElement("div"); div.innerHTML = String(coord); div.style.width = this.tileSize.width + "px"; div.style.height = this.tileSize.height + "px"; div.style.fontSize = "10"; div.style.borderStyle = "solid"; div.style.borderWidth = "1px"; div.style.borderColor = "#AAAAAA"; div.style.backgroundColor = "#E5E3DF"; return div; } releaseTile(tile: HTMLElement): void {} } function initMap(): void { const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { zoom: 10, center: { lat: 41.85, lng: -87.65 }, streetViewControl: false, mapTypeId: "coordinate", mapTypeControlOptions: { mapTypeIds: ["coordinate", "roadmap"], style: google.maps.MapTypeControlStyle.DROPDOWN_MENU, }, } ); map.addListener("maptypeid_changed", () => { const showStreetViewControl = (map.getMapTypeId() as string) !== "coordinate"; map.setOptions({ streetViewControl: showStreetViewControl, }); }); // Now attach the coordinate map type to the map's registry. map.mapTypes.set( "coordinate", new CoordMapType(new google.maps.Size(256, 256)) ); } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
/* * This demo demonstrates how to replace default map tiles with custom imagery. * In this case, the CoordMapType displays gray tiles annotated with the tile * coordinates. * * Try panning and zooming the map to see how the coordinates change. */ class CoordMapType { tileSize; maxZoom = 19; name = "Tile #s"; alt = "Tile Coordinate Map Type"; constructor(tileSize) { this.tileSize = tileSize; } getTile(coord, zoom, ownerDocument) { const div = ownerDocument.createElement("div"); div.innerHTML = String(coord); div.style.width = this.tileSize.width + "px"; div.style.height = this.tileSize.height + "px"; div.style.fontSize = "10"; div.style.borderStyle = "solid"; div.style.borderWidth = "1px"; div.style.borderColor = "#AAAAAA"; div.style.backgroundColor = "#E5E3DF"; return div; } releaseTile(tile) {} } function initMap() { const map = new google.maps.Map(document.getElementById("map"), { zoom: 10, center: { lat: 41.85, lng: -87.65 }, streetViewControl: false, mapTypeId: "coordinate", mapTypeControlOptions: { mapTypeIds: ["coordinate", "roadmap"], style: google.maps.MapTypeControlStyle.DROPDOWN_MENU, }, }); map.addListener("maptypeid_changed", () => { const showStreetViewControl = map.getMapTypeId() !== "coordinate"; map.setOptions({ streetViewControl: showStreetViewControl, }); }); // Now attach the coordinate map type to the map's registry. map.mapTypes.set( "coordinate", new CoordMapType(new google.maps.Size(256, 256)), ); } window.initMap = initMap;
Dùng thử mẫu
Các loại bản đồ lớp phủ
Một số loại bản đồ được thiết kế để hoạt động trên bản đồ hiện có loại. Các loại bản đồ như vậy có thể có các lớp trong suốt cho biết địa điểm yêu thích hoặc hiển thị thêm dữ liệu cho người dùng.
Trong những trường hợp này, bạn không muốn xem loại bản đồ là một thực thể riêng biệt mà là một lớp phủ.
Bạn có thể thực hiện việc này bằng cách trực tiếp thêm loại bản đồ vào MapType
hiện có bằng cách sử dụng
thuộc tính overlayMapTypes
của Map
. Tài sản này chứa
MVCArray
/MapType
. Tất cả các loại bản đồ
(cơ sở và lớp phủ) được hiển thị trong
mapPane
lớp. Các loại bản đồ lớp phủ sẽ hiển thị ở đầu bản đồ cơ sở mà chúng sẽ hiển thị
được đính kèm theo thứ tự mà chúng xuất hiện trong
Mảng Map.overlayMapTypes
(lớp phủ có chỉ mục cao hơn
được hiển thị trước lớp phủ có giá trị chỉ mục thấp hơn).
Ví dụ sau giống với ví dụ trước
ngoại trừ việc chúng ta đã tạo lớp phủ ô MapType
ở đầu loại bản đồ ROADMAP
:
TypeScript
/* * This demo illustrates the coordinate system used to display map tiles in the * API. * * Tiles in Google Maps are numbered from the same origin as that for * pixels. For Google's implementation of the Mercator projection, the origin * tile is always at the northwest corner of the map, with x values increasing * from west to east and y values increasing from north to south. * * Try panning and zooming the map to see how the coordinates change. */ class CoordMapType implements google.maps.MapType { tileSize: google.maps.Size; alt: string|null = null; maxZoom: number = 17; minZoom: number = 0; name: string|null = null; projection: google.maps.Projection|null = null; radius: number = 6378137; constructor(tileSize: google.maps.Size) { this.tileSize = tileSize; } getTile( coord: google.maps.Point, zoom: number, ownerDocument: Document ): HTMLElement { const div = ownerDocument.createElement("div"); div.innerHTML = String(coord); div.style.width = this.tileSize.width + "px"; div.style.height = this.tileSize.height + "px"; div.style.fontSize = "10"; div.style.borderStyle = "solid"; div.style.borderWidth = "1px"; div.style.borderColor = "#AAAAAA"; return div; } releaseTile(tile: Element): void {} } function initMap(): void { const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { zoom: 10, center: { lat: 41.85, lng: -87.65 }, } ); // Insert this overlay map type as the first overlay map type at // position 0. Note that all overlay map types appear on top of // their parent base map. const coordMapType = new CoordMapType(new google.maps.Size(256, 256)) map.overlayMapTypes.insertAt( 0, coordMapType ); } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
/* * This demo illustrates the coordinate system used to display map tiles in the * API. * * Tiles in Google Maps are numbered from the same origin as that for * pixels. For Google's implementation of the Mercator projection, the origin * tile is always at the northwest corner of the map, with x values increasing * from west to east and y values increasing from north to south. * * Try panning and zooming the map to see how the coordinates change. */ class CoordMapType { tileSize; alt = null; maxZoom = 17; minZoom = 0; name = null; projection = null; radius = 6378137; constructor(tileSize) { this.tileSize = tileSize; } getTile(coord, zoom, ownerDocument) { const div = ownerDocument.createElement("div"); div.innerHTML = String(coord); div.style.width = this.tileSize.width + "px"; div.style.height = this.tileSize.height + "px"; div.style.fontSize = "10"; div.style.borderStyle = "solid"; div.style.borderWidth = "1px"; div.style.borderColor = "#AAAAAA"; return div; } releaseTile(tile) {} } function initMap() { const map = new google.maps.Map(document.getElementById("map"), { zoom: 10, center: { lat: 41.85, lng: -87.65 }, }); // Insert this overlay map type as the first overlay map type at // position 0. Note that all overlay map types appear on top of // their parent base map. const coordMapType = new CoordMapType(new google.maps.Size(256, 256)); map.overlayMapTypes.insertAt(0, coordMapType); } window.initMap = initMap;
Dùng thử mẫu
Các loại bản đồ hình ảnh
Triển khai MapType
để đóng vai trò là bản đồ cơ sở
có thể là một nhiệm vụ tốn thời gian và tốn công sức. API
cung cấp một lớp đặc biệt triển khai MapType
giao diện cho các loại bản đồ phổ biến nhất: các loại bản đồ có chứa
ô được tạo thành từ các tệp hình ảnh đơn.
Lớp này (lớp ImageMapType
)
được tạo bằng ImageMapTypeOptions
quy cách đối tượng xác định các thông số bắt buộc sau
thuộc tính:
tileSize
(bắt buộc) chỉ định kích thước của ô (thuộc loạigoogle.maps.Size
). Kích thước phải là hình chữ nhật nhưng không cần phải là hình vuông.getTileUrl
(bắt buộc) chỉ định hàm, thường được cung cấp dưới dạng giá trị cố định của hàm cùng dòng, để xử lý lựa chọn ô hình ảnh thích hợp dựa trên ô đã cung cấp toạ độ thế giới và mức độ thu phóng.
Mã sau đây sẽ triển khai một ImageMapType
cơ bản
bằng cách sử dụng các ô mặt trăng của Google. Ví dụ này sử dụng quá trình chuẩn hoá
để đảm bảo các hình xếp lặp lại dọc theo trục x, nhưng không dọc theo trục x
trục y của bản đồ.
TypeScript
function initMap(): void { const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { center: { lat: 0, lng: 0 }, zoom: 1, streetViewControl: false, mapTypeControlOptions: { mapTypeIds: ["moon"], }, } ); const moonMapType = new google.maps.ImageMapType({ getTileUrl: function (coord, zoom): string { const normalizedCoord = getNormalizedCoord(coord, zoom); if (!normalizedCoord) { return ""; } const bound = Math.pow(2, zoom); return ( "https://mw1.google.com/mw-planetary/lunar/lunarmaps_v1/clem_bw" + "/" + zoom + "/" + normalizedCoord.x + "/" + (bound - normalizedCoord.y - 1) + ".jpg" ); }, tileSize: new google.maps.Size(256, 256), maxZoom: 9, minZoom: 0, // @ts-ignore TODO 'radius' does not exist in type 'ImageMapTypeOptions' radius: 1738000, name: "Moon", }); map.mapTypes.set("moon", moonMapType); map.setMapTypeId("moon"); } // Normalizes the coords that tiles repeat across the x axis (horizontally) // like the standard Google map tiles. function getNormalizedCoord(coord, zoom) { const y = coord.y; let x = coord.x; // tile range in one direction range is dependent on zoom level // 0 = 1 tile, 1 = 2 tiles, 2 = 4 tiles, 3 = 8 tiles, etc const tileRange = 1 << zoom; // don't repeat across y-axis (vertically) if (y < 0 || y >= tileRange) { return null; } // repeat across x-axis if (x < 0 || x >= tileRange) { x = ((x % tileRange) + tileRange) % tileRange; } return { x: x, y: y }; } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
function initMap() { const map = new google.maps.Map(document.getElementById("map"), { center: { lat: 0, lng: 0 }, zoom: 1, streetViewControl: false, mapTypeControlOptions: { mapTypeIds: ["moon"], }, }); const moonMapType = new google.maps.ImageMapType({ getTileUrl: function (coord, zoom) { const normalizedCoord = getNormalizedCoord(coord, zoom); if (!normalizedCoord) { return ""; } const bound = Math.pow(2, zoom); return ( "https://mw1.google.com/mw-planetary/lunar/lunarmaps_v1/clem_bw" + "/" + zoom + "/" + normalizedCoord.x + "/" + (bound - normalizedCoord.y - 1) + ".jpg" ); }, tileSize: new google.maps.Size(256, 256), maxZoom: 9, minZoom: 0, // @ts-ignore TODO 'radius' does not exist in type 'ImageMapTypeOptions' radius: 1738000, name: "Moon", }); map.mapTypes.set("moon", moonMapType); map.setMapTypeId("moon"); } // Normalizes the coords that tiles repeat across the x axis (horizontally) // like the standard Google map tiles. function getNormalizedCoord(coord, zoom) { const y = coord.y; let x = coord.x; // tile range in one direction range is dependent on zoom level // 0 = 1 tile, 1 = 2 tiles, 2 = 4 tiles, 3 = 8 tiles, etc const tileRange = 1 << zoom; // don't repeat across y-axis (vertically) if (y < 0 || y >= tileRange) { return null; } // repeat across x-axis if (x < 0 || x >= tileRange) { x = ((x % tileRange) + tileRange) % tileRange; } return { x: x, y: y }; } window.initMap = initMap;
Dùng thử mẫu
Dự đoán
Trái Đất là một hình cầu ba chiều (xấp xỉ), trong khi bản đồ là một bề mặt phẳng hai chiều. Bản đồ mà bạn thấy trong đó API JavaScript của Maps, giống như bất kỳ bản đồ phẳng nào trên Trái đất, là một hình chiếu của hình cầu đó lên một bề mặt phẳng. Đơn giản nhất phép chiếu có thể được định nghĩa là ánh xạ giá trị vĩ độ/kinh độ thành toạ độ trên bản đồ của phép chiếu.
Các phép chiếu trong API JavaScript của Maps phải triển khai
Giao diện Projection
. Một Projection
Việc triển khai phải cung cấp không chỉ ánh xạ từ một toạ độ
hệ thống này sang một hệ thống khác mà là ánh xạ hai chiều. Tức là bạn phải
xác định cách dịch từ toạ độ Earth (LatLng
đối tượng)
vào lớp Projection
thế giới
hệ toạ độ và ngược lại. Google Maps sử dụng
phép chiếu Mercator để tạo bản đồ của nó
từ dữ liệu địa lý và chuyển đổi các sự kiện trên bản đồ thành
toạ độ địa lý. Bạn có thể lấy phép chiếu này bằng cách
đang gọi getProjection()
trên Map
(hoặc bất kỳ loại MapType
cơ sở tiêu chuẩn nào). Trong hầu hết trường hợp,
Projection
tiêu chuẩn này là đủ, nhưng bạn cũng có thể
xác định và sử dụng phép chiếu tuỳ chỉnh của riêng bạn.
Triển khai phép chiếu
Khi triển khai phép chiếu tuỳ chỉnh, bạn sẽ cần xác định một vài điều:
- Công thức để lập bản đồ toạ độ theo vĩ độ và kinh độ vào
máy bay Descartes và ngược lại. (Giao diện
Projection
chỉ hỗ trợ phép biến đổi thành toạ độ thẳng.) - Kích thước ô cơ sở. Tất cả các ô phải là hình chữ nhật.
- "Quy mô thế giới" của bản đồ bằng cách sử dụng ô cơ sở được đặt ở mức thu phóng 0. Lưu ý rằng đối với bản đồ chứa một ô ở mức thu phóng bằng 0, kích thước thế giới và kích thước ô cơ sở là giống hệt nhau.
Phối hợp chuyển đổi trong Dự đoán
Mỗi phép chiếu cung cấp hai phương thức để chuyển đổi giữa hai phép chiếu này hệ thống toạ độ, cho phép bạn chuyển đổi giữa toạ độ thế giới:
- Phương thức
Projection.fromLatLngToPoint()
chuyển đổi một Giá trịLatLng
thành toạ độ thế giới. Phương thức này được sử dụng để định vị các lớp phủ trên bản đồ (và để định vị chính bản đồ). - Phương thức
Projection.fromPointToLatLng()
chuyển đổi một toạ độ thế giới thành giá trịLatLng
. Chiến dịch này được sử dụng để chuyển đổi các sự kiện, chẳng hạn như lượt nhấp xảy ra trên bản đồ theo toạ độ địa lý.
Google Maps giả định rằng phép chiếu là trực tuyến.
Thông thường, bạn có thể sử dụng phép chiếu cho hai trường hợp: để tạo một bản đồ thế giới hoặc để tạo bản đồ cho một khu vực địa phương. Trong trường hợp cũ, bạn phải đảm bảo rằng phép chiếu cũng thẳng và thẳng ở mọi kinh độ. Một số phép chiếu (đặc biệt là phép chiếu conic) có thể là "bình thường tại địa phương" (tức là hướng về phía bắc) nhưng lại chệch khỏi hướng chính bắc; ví dụ: bản đồ được định vị càng xa so với một số kinh độ tham chiếu. Bạn có thể sử dụng phép chiếu như vậy cục bộ, nhưng biết rằng phép chiếu nhất thiết không chính xác và có sự biến đổi lỗi sẽ ngày càng rõ ràng hơn, kinh độ tham chiếu mà bạn lệch.
Lựa chọn ô bản đồ trong phép chiếu
Phép chiếu không chỉ hữu ích cho việc xác định vị trí của
vị trí hoặc lớp phủ, mà để định vị các ô bản đồ.
API JavaScript của Maps kết xuất các bản đồ cơ sở bằng cách sử dụng một MapType
Giao diện này phải khai báo cả thuộc tính projection
cho
xác định phép chiếu của bản đồ và getTile()
để truy xuất ô bản đồ dựa trên
ô
toạ độ. Toạ độ ô dựa trên
cả kích thước ô cơ bản (phải là hình chữ nhật) và
kích thước" của bản đồ, tức là kích thước pixel của thế giới bản đồ
ở mức thu phóng 0. (Đối với bản đồ bao gồm một ô ở mức thu phóng 0, ô này
quy mô và quy mô thế giới là như nhau.)
Bạn xác định kích thước ô cơ sở trong phần tử của MapType
Thuộc tính tileSize
. Bạn tự xác định kích thước thế giới
trong fromLatLngToPoint()
của phép chiếu
và phương thức fromPointToLatLng()
.
Vì việc lựa chọn hình ảnh phụ thuộc vào các giá trị được truyền này nên sẽ rất hữu ích
để đặt tên cho những hình ảnh có thể được chọn theo phương thức lập trình.
giá trị đã chuyển, chẳng hạn như
map_zoom_tileX_tileY.png
.
Ví dụ sau đây định nghĩa ImageMapType
sử dụng
Phép chiếu Gall-Peters:
TypeScript
// This example defines an image map type using the Gall-Peters // projection. // https://en.wikipedia.org/wiki/Gall%E2%80%93Peters_projection function initMap(): void { // Create a map. Use the Gall-Peters map type. const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { zoom: 0, center: { lat: 0, lng: 0 }, mapTypeControl: false, } ); initGallPeters(); map.mapTypes.set("gallPeters", gallPetersMapType); map.setMapTypeId("gallPeters"); // Show the lat and lng under the mouse cursor. const coordsDiv = document.getElementById("coords") as HTMLElement; map.controls[google.maps.ControlPosition.TOP_CENTER].push(coordsDiv); map.addListener("mousemove", (event: google.maps.MapMouseEvent) => { coordsDiv.textContent = "lat: " + Math.round(event.latLng!.lat()) + ", " + "lng: " + Math.round(event.latLng!.lng()); }); // Add some markers to the map. map.data.setStyle((feature) => { return { title: feature.getProperty("name") as string, optimized: false, }; }); map.data.addGeoJson(cities); } let gallPetersMapType; function initGallPeters() { const GALL_PETERS_RANGE_X = 800; const GALL_PETERS_RANGE_Y = 512; // Fetch Gall-Peters tiles stored locally on our server. gallPetersMapType = new google.maps.ImageMapType({ getTileUrl: function (coord, zoom) { const scale = 1 << zoom; // Wrap tiles horizontally. const x = ((coord.x % scale) + scale) % scale; // Don't wrap tiles vertically. const y = coord.y; if (y < 0 || y >= scale) return ""; return ( "https://developers.google.com/maps/documentation/" + "javascript/examples/full/images/gall-peters_" + zoom + "_" + x + "_" + y + ".png" ); }, tileSize: new google.maps.Size(GALL_PETERS_RANGE_X, GALL_PETERS_RANGE_Y), minZoom: 0, maxZoom: 1, name: "Gall-Peters", }); // Describe the Gall-Peters projection used by these tiles. gallPetersMapType.projection = { fromLatLngToPoint: function (latLng) { const latRadians = (latLng.lat() * Math.PI) / 180; return new google.maps.Point( GALL_PETERS_RANGE_X * (0.5 + latLng.lng() / 360), GALL_PETERS_RANGE_Y * (0.5 - 0.5 * Math.sin(latRadians)) ); }, fromPointToLatLng: function (point, noWrap) { const x = point.x / GALL_PETERS_RANGE_X; const y = Math.max(0, Math.min(1, point.y / GALL_PETERS_RANGE_Y)); return new google.maps.LatLng( (Math.asin(1 - 2 * y) * 180) / Math.PI, -180 + 360 * x, noWrap ); }, }; } // GeoJSON, describing the locations and names of some cities. const cities = { type: "FeatureCollection", features: [ { type: "Feature", geometry: { type: "Point", coordinates: [-87.65, 41.85] }, properties: { name: "Chicago" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [-149.9, 61.218] }, properties: { name: "Anchorage" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [-99.127, 19.427] }, properties: { name: "Mexico City" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [-0.126, 51.5] }, properties: { name: "London" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [28.045, -26.201] }, properties: { name: "Johannesburg" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [15.322, -4.325] }, properties: { name: "Kinshasa" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [151.207, -33.867] }, properties: { name: "Sydney" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [0, 0] }, properties: { name: "0°N 0°E" }, }, ], }; declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
// This example defines an image map type using the Gall-Peters // projection. // https://en.wikipedia.org/wiki/Gall%E2%80%93Peters_projection function initMap() { // Create a map. Use the Gall-Peters map type. const map = new google.maps.Map(document.getElementById("map"), { zoom: 0, center: { lat: 0, lng: 0 }, mapTypeControl: false, }); initGallPeters(); map.mapTypes.set("gallPeters", gallPetersMapType); map.setMapTypeId("gallPeters"); // Show the lat and lng under the mouse cursor. const coordsDiv = document.getElementById("coords"); map.controls[google.maps.ControlPosition.TOP_CENTER].push(coordsDiv); map.addListener("mousemove", (event) => { coordsDiv.textContent = "lat: " + Math.round(event.latLng.lat()) + ", " + "lng: " + Math.round(event.latLng.lng()); }); // Add some markers to the map. map.data.setStyle((feature) => { return { title: feature.getProperty("name"), optimized: false, }; }); map.data.addGeoJson(cities); } let gallPetersMapType; function initGallPeters() { const GALL_PETERS_RANGE_X = 800; const GALL_PETERS_RANGE_Y = 512; // Fetch Gall-Peters tiles stored locally on our server. gallPetersMapType = new google.maps.ImageMapType({ getTileUrl: function (coord, zoom) { const scale = 1 << zoom; // Wrap tiles horizontally. const x = ((coord.x % scale) + scale) % scale; // Don't wrap tiles vertically. const y = coord.y; if (y < 0 || y >= scale) return ""; return ( "https://developers.google.com/maps/documentation/" + "javascript/examples/full/images/gall-peters_" + zoom + "_" + x + "_" + y + ".png" ); }, tileSize: new google.maps.Size(GALL_PETERS_RANGE_X, GALL_PETERS_RANGE_Y), minZoom: 0, maxZoom: 1, name: "Gall-Peters", }); // Describe the Gall-Peters projection used by these tiles. gallPetersMapType.projection = { fromLatLngToPoint: function (latLng) { const latRadians = (latLng.lat() * Math.PI) / 180; return new google.maps.Point( GALL_PETERS_RANGE_X * (0.5 + latLng.lng() / 360), GALL_PETERS_RANGE_Y * (0.5 - 0.5 * Math.sin(latRadians)), ); }, fromPointToLatLng: function (point, noWrap) { const x = point.x / GALL_PETERS_RANGE_X; const y = Math.max(0, Math.min(1, point.y / GALL_PETERS_RANGE_Y)); return new google.maps.LatLng( (Math.asin(1 - 2 * y) * 180) / Math.PI, -180 + 360 * x, noWrap, ); }, }; } // GeoJSON, describing the locations and names of some cities. const cities = { type: "FeatureCollection", features: [ { type: "Feature", geometry: { type: "Point", coordinates: [-87.65, 41.85] }, properties: { name: "Chicago" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [-149.9, 61.218] }, properties: { name: "Anchorage" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [-99.127, 19.427] }, properties: { name: "Mexico City" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [-0.126, 51.5] }, properties: { name: "London" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [28.045, -26.201] }, properties: { name: "Johannesburg" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [15.322, -4.325] }, properties: { name: "Kinshasa" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [151.207, -33.867] }, properties: { name: "Sydney" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [0, 0] }, properties: { name: "0°N 0°E" }, }, ], }; window.initMap = initMap;