ข้อมูลเบื้องต้น
การวางซ้อนคือวัตถุบนแผนที่ที่เชื่อมโยงกับพิกัดละติจูด/ลองจิจูด วัตถุเหล่านั้นจึงเคลื่อนที่เมื่อคุณลากหรือซูมแผนที่ สําหรับข้อมูลเกี่ยวกับประเภทการวางซ้อนที่กําหนดไว้ล่วงหน้า โปรดดูการวาดบนแผนที่
Maps JavaScript API มีคลาส OverlayView
สําหรับสร้างโฆษณาซ้อนทับที่กําหนดเอง OverlayView
เป็นคลาสพื้นฐานที่มีวิธีการหลายอย่างที่คุณต้องใช้เมื่อสร้างการวางซ้อน คลาสนี้ยังเสนอวิธีการ 2-3 วิธีในการแปลค่าระหว่างพิกัดหน้าจอและตําแหน่งบนแผนที่
เพิ่มการวางซ้อนที่กําหนดเอง
ต่อไปนี้คือสรุปขั้นตอนที่จําเป็นในการสร้างการวางซ้อนที่กําหนดเอง
- ตั้งค่า
prototype
ของออบเจ็กต์การซ้อนทับที่กําหนดเองเป็นอินสแตนซ์ใหม่ของgoogle.maps.OverlayView()
ก็จะมีคลาสการวางซ้อน คลาสแบบวางซ้อนอยู่ - สร้างเครื่องมือสร้างสําหรับโฆษณาซ้อนทับที่กําหนดเอง และตั้งค่าพารามิเตอร์การเริ่มต้น
- ติดตั้งเมธอด
onAdd()
ภายในต้นแบบของคุณ แล้วนําไปแนบกับแผนที่ ระบบจะเรียกOverlayView.onAdd()
เมื่อแผนที่พร้อมสําหรับโฆษณาซ้อนทับ - ติดตั้งเมธอด
draw()
ภายในต้นแบบของคุณ แล้วจัดการการแสดงภาพของออบเจ็กต์ ระบบจะเรียกOverlayView.draw()
เมื่อออบเจ็กต์ปรากฏเป็นครั้งแรก - นอกจากนี้ คุณควรใช้เมธอด
onRemove()
เพื่อล้างองค์ประกอบต่างๆ ที่คุณเพิ่มลงในโฆษณาซ้อนทับด้วย
โปรดดูรายละเอียดเพิ่มเติมของแต่ละขั้นตอนด้านล่าง คุณสามารถดูโค้ดตัวอย่างแบบเต็มที่ ทํางาน: ดูโค้ดตัวอย่าง
ประเภทย่อยของการวางซ้อน
ตัวอย่างด้านล่างใช้ OverlayView
เพื่อสร้างภาพซ้อนทับอย่างง่าย
ตอนนี้เราจะสร้างเครื่องมือสร้างสําหรับคลาส USGSOverlay
และเริ่มพารามิเตอร์ที่ผ่านเป็นคุณสมบัติของออบเจ็กต์ใหม่
TypeScript
/** * The custom USGSOverlay object contains the USGS image, * the bounds of the image, and a reference to the map. */ class USGSOverlay extends google.maps.OverlayView { private bounds: google.maps.LatLngBounds; private image: string; private div?: HTMLElement; constructor(bounds: google.maps.LatLngBounds, image: string) { super(); this.bounds = bounds; this.image = image; }
JavaScript
/** * The custom USGSOverlay object contains the USGS image, * the bounds of the image, and a reference to the map. */ class USGSOverlay extends google.maps.OverlayView { bounds; image; div; constructor(bounds, image) { super(); this.bounds = bounds; this.image = image; }
เรายังไม่สามารถแนบภาพซ้อนทับนี้ไปยังแผนที่ในตัวสร้างของภาพซ้อนทับ ก่อนอื่น เราต้องตรวจสอบให้แน่ใจว่าบานหน้าต่างทั้งหมดของแผนที่พร้อมใช้งาน เนื่องจากหน้าต่างเหล่านั้นระบุลําดับการแสดงวัตถุบนแผนที่ API นี้มอบวิธีตัวช่วยที่บ่งบอกว่าเหตุการณ์นี้เกิดขึ้น เราจะจัดการวิธีดังกล่าว ในส่วนถัดไป
เริ่มต้นการวางซ้อน
เมื่อระบบทําการวางซ้อนเป็นครั้งแรกและพร้อมที่จะแสดง เราต้องแนบแผนที่ไปกับ DOM ของเบราว์เซอร์ API บ่งชี้ว่ามีการเพิ่มโฆษณาซ้อนทับลงในแผนที่แล้ว โดยการเรียกใช้เมธอด onAdd()
ของโฆษณาซ้อนทับ สําหรับวิธีนี้
เราสร้าง <div>
เพื่อเก็บภาพของเรา เพิ่มองค์ประกอบ <img>
แนบองค์ประกอบนั้นกับ <div>
แล้วแนบภาพซ้อนทับกับแผงของแผนที่แบบใดแบบหนึ่ง บานหน้าต่างคือโหนดภายในโครงสร้าง DOM
ช่องของประเภท
MapPanes
จะระบุลําดับการเรียงซ้อนเลเยอร์ต่างๆ บนแผนที่ แผงต่อไปนี้จะมีอยู่และแจกแจงตามลําดับที่เรียงจากล่างขึ้นบน
mapPane
เป็นแผงที่ต่ําที่สุดและอยู่เหนือไทล์ แต่อาจไม่ได้รับเหตุการณ์ DOM (ย่อหน้า 0)overlayLayer
มีโพลีไลน์ รูปหลายเหลี่ยม การวางซ้อนพื้น และการวางซ้อนเลเยอร์แผนที่ อุปกรณ์อาจไม่ได้รับเหตุการณ์ DOM (ช่อง 1)markerLayer
มีเครื่องหมาย อุปกรณ์อาจไม่ได้รับเหตุการณ์ DOM (ช่อง 2)overlayMouseTarget
มีองค์ประกอบที่ได้รับเหตุการณ์ DOM (ช่อง 3)floatPane
มีหน้าต่างข้อมูล ซึ่งอยู่เหนือการวางซ้อนแผนที่ทั้งหมด (ย่อหน้า 4)
เนื่องจากภาพของเราเป็น "การวางซ้อนพื้น" เราจึงใช้แผง overlayLayer
เมื่อมีช่องนั้นแล้ว เราจะแนบวัตถุนั้นไว้เป็นรายการย่อย
TypeScript
/** * onAdd is called when the map's panes are ready and the overlay has been * added to the map. */ onAdd() { this.div = document.createElement("div"); this.div.style.borderStyle = "none"; this.div.style.borderWidth = "0px"; this.div.style.position = "absolute"; // Create the img element and attach it to the div. const img = document.createElement("img"); img.src = this.image; img.style.width = "100%"; img.style.height = "100%"; img.style.position = "absolute"; this.div.appendChild(img); // Add the element to the "overlayLayer" pane. const panes = this.getPanes()!; panes.overlayLayer.appendChild(this.div); }
JavaScript
/** * onAdd is called when the map's panes are ready and the overlay has been * added to the map. */ onAdd() { this.div = document.createElement("div"); this.div.style.borderStyle = "none"; this.div.style.borderWidth = "0px"; this.div.style.position = "absolute"; // Create the img element and attach it to the div. const img = document.createElement("img"); img.src = this.image; img.style.width = "100%"; img.style.height = "100%"; img.style.position = "absolute"; this.div.appendChild(img); // Add the element to the "overlayLayer" pane. const panes = this.getPanes(); panes.overlayLayer.appendChild(this.div); }
วาดการซ้อนทับ
โปรดทราบว่าเราไม่ได้เรียกใช้การแสดงผลภาพพิเศษใดๆ ในโค้ดด้านบน API จะเรียกเมธอด draw()
แยกต่างหากในโฆษณาซ้อนทับเมื่อใดก็ตามที่ต้องการวาดโฆษณาซ้อนทับบนแผนที่ ซึ่งรวมถึงเวลาที่เพิ่มเป็นครั้งแรกด้วย
ดังนั้นเราจะใช้วิธีการ draw()
นี้ ดึงข้อมูล MapCanvasProjection
ของภาพซ้อนทับโดยใช้ getProjection()
และคํานวณพิกัดที่แน่นอนที่จะเชื่อมโยงกับจุดบนขวาและซ้ายของวัตถุ
จากนั้นเราจะปรับขนาด <div>
ได้ เพื่อปรับขนาดภาพให้ตรงตามขอบเขต
ที่เรากําหนดในเครื่องมือสร้างการวางซ้อน
TypeScript
draw() { // We use the south-west and north-east // coordinates of the overlay to peg it to the correct position and size. // To do this, we need to retrieve the projection from the overlay. const overlayProjection = this.getProjection(); // Retrieve the south-west and north-east coordinates of this overlay // in LatLngs and convert them to pixel coordinates. // We'll use these coordinates to resize the div. const sw = overlayProjection.fromLatLngToDivPixel( this.bounds.getSouthWest() )!; const ne = overlayProjection.fromLatLngToDivPixel( this.bounds.getNorthEast() )!; // Resize the image's div to fit the indicated dimensions. if (this.div) { this.div.style.left = sw.x + "px"; this.div.style.top = ne.y + "px"; this.div.style.width = ne.x - sw.x + "px"; this.div.style.height = sw.y - ne.y + "px"; } }
JavaScript
draw() { // We use the south-west and north-east // coordinates of the overlay to peg it to the correct position and size. // To do this, we need to retrieve the projection from the overlay. const overlayProjection = this.getProjection(); // Retrieve the south-west and north-east coordinates of this overlay // in LatLngs and convert them to pixel coordinates. // We'll use these coordinates to resize the div. const sw = overlayProjection.fromLatLngToDivPixel( this.bounds.getSouthWest() ); const ne = overlayProjection.fromLatLngToDivPixel( this.bounds.getNorthEast() ); // Resize the image's div to fit the indicated dimensions. if (this.div) { this.div.style.left = sw.x + "px"; this.div.style.top = ne.y + "px"; this.div.style.width = ne.x - sw.x + "px"; this.div.style.height = sw.y - ne.y + "px"; } }
นําการวางซ้อนที่กําหนดเองออก
นอกจากนี้ เรายังเพิ่มเมธอด onRemove()
เพื่อลบการวางซ้อนออกจากแผนที่อย่างแม่นยํา
TypeScript
/** * The onRemove() method will be called automatically from the API if * we ever set the overlay's map property to 'null'. */ onRemove() { if (this.div) { (this.div.parentNode as HTMLElement).removeChild(this.div); delete this.div; } }
JavaScript
/** * The onRemove() method will be called automatically from the API if * we ever set the overlay's map property to 'null'. */ onRemove() { if (this.div) { this.div.parentNode.removeChild(this.div); delete this.div; } }
ซ่อนและแสดงการวางซ้อนที่กําหนดเอง
ถ้าคุณต้องการซ่อนหรือแสดงภาพซ้อนทับแทนการสร้างหรือนําออก
คุณสามารถใช้วิธีการ hide()
และ show()
ของคุณเองเพื่อปรับการเปิดเผย
ของการวางซ้อน หรือคุณสามารถนําการวางซ้อนออกจาก DOM ของแผนที่ได้
แม้ว่าการดําเนินการนี้จะมีค่าใช้จ่ายสูงกว่าเล็กน้อย โปรดทราบว่าหากคุณใส่การวางซ้อนลงใน DOM ของแผนที่อีกครั้ง จะเรียกใช้เมธอด onAdd()
ของโฆษณาซ้อนทับอีกครั้ง
ตัวอย่างต่อไปนี้เพิ่มเมธอด hide()
และ show()
ลงในต้นแบบของโฆษณาซ้อนทับ ซึ่งจะสลับการมองเห็นคอนเทนเนอร์ <div>
นอกจากนี้ เรายังเพิ่มเมธอด toggleDOM()
ซึ่งจะแนบหรือถอดการซ้อนทับออกจาก/ออกจากแผนที่
TypeScript
/** * Set the visibility to 'hidden' or 'visible'. */ hide() { if (this.div) { this.div.style.visibility = "hidden"; } } show() { if (this.div) { this.div.style.visibility = "visible"; } } toggle() { if (this.div) { if (this.div.style.visibility === "hidden") { this.show(); } else { this.hide(); } } } toggleDOM(map: google.maps.Map) { if (this.getMap()) { this.setMap(null); } else { this.setMap(map); } }
JavaScript
/** * Set the visibility to 'hidden' or 'visible'. */ hide() { if (this.div) { this.div.style.visibility = "hidden"; } } show() { if (this.div) { this.div.style.visibility = "visible"; } } toggle() { if (this.div) { if (this.div.style.visibility === "hidden") { this.show(); } else { this.hide(); } } } toggleDOM(map) { if (this.getMap()) { this.setMap(null); } else { this.setMap(map); } }
เพิ่มปุ่มควบคุม
หากต้องการทริกเกอร์เมธอด toggle
และ toggleDom
ระบบจะเพิ่มตัวควบคุมปุ่มลงในแผนที่
TypeScript
const toggleButton = document.createElement("button"); toggleButton.textContent = "Toggle"; toggleButton.classList.add("custom-map-control-button"); const toggleDOMButton = document.createElement("button"); toggleDOMButton.textContent = "Toggle DOM Attachment"; toggleDOMButton.classList.add("custom-map-control-button"); toggleButton.addEventListener("click", () => { overlay.toggle(); }); toggleDOMButton.addEventListener("click", () => { overlay.toggleDOM(map); }); map.controls[google.maps.ControlPosition.TOP_RIGHT].push(toggleDOMButton); map.controls[google.maps.ControlPosition.TOP_RIGHT].push(toggleButton);
JavaScript
const toggleButton = document.createElement("button"); toggleButton.textContent = "Toggle"; toggleButton.classList.add("custom-map-control-button"); const toggleDOMButton = document.createElement("button"); toggleDOMButton.textContent = "Toggle DOM Attachment"; toggleDOMButton.classList.add("custom-map-control-button"); toggleButton.addEventListener("click", () => { overlay.toggle(); }); toggleDOMButton.addEventListener("click", () => { overlay.toggleDOM(map); }); map.controls[google.maps.ControlPosition.TOP_RIGHT].push(toggleDOMButton); map.controls[google.maps.ControlPosition.TOP_RIGHT].push(toggleButton);
โค้ดตัวอย่างที่สมบูรณ์
ตัวอย่างโค้ดที่สมบูรณ์มีดังนี้
TypeScript
// This example adds hide() and show() methods to a custom overlay's prototype. // These methods toggle the visibility of the container <div>. // overlay to or from the map. function initMap(): void { const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { zoom: 11, center: { lat: 62.323907, lng: -150.109291 }, mapTypeId: "satellite", } ); const bounds = new google.maps.LatLngBounds( new google.maps.LatLng(62.281819, -150.287132), new google.maps.LatLng(62.400471, -150.005608) ); // The photograph is courtesy of the U.S. Geological Survey. let image = "https://developers.google.com/maps/documentation/javascript/"; image += "examples/full/images/talkeetna.png"; /** * The custom USGSOverlay object contains the USGS image, * the bounds of the image, and a reference to the map. */ class USGSOverlay extends google.maps.OverlayView { private bounds: google.maps.LatLngBounds; private image: string; private div?: HTMLElement; constructor(bounds: google.maps.LatLngBounds, image: string) { super(); this.bounds = bounds; this.image = image; } /** * onAdd is called when the map's panes are ready and the overlay has been * added to the map. */ onAdd() { this.div = document.createElement("div"); this.div.style.borderStyle = "none"; this.div.style.borderWidth = "0px"; this.div.style.position = "absolute"; // Create the img element and attach it to the div. const img = document.createElement("img"); img.src = this.image; img.style.width = "100%"; img.style.height = "100%"; img.style.position = "absolute"; this.div.appendChild(img); // Add the element to the "overlayLayer" pane. const panes = this.getPanes()!; panes.overlayLayer.appendChild(this.div); } draw() { // We use the south-west and north-east // coordinates of the overlay to peg it to the correct position and size. // To do this, we need to retrieve the projection from the overlay. const overlayProjection = this.getProjection(); // Retrieve the south-west and north-east coordinates of this overlay // in LatLngs and convert them to pixel coordinates. // We'll use these coordinates to resize the div. const sw = overlayProjection.fromLatLngToDivPixel( this.bounds.getSouthWest() )!; const ne = overlayProjection.fromLatLngToDivPixel( this.bounds.getNorthEast() )!; // Resize the image's div to fit the indicated dimensions. if (this.div) { this.div.style.left = sw.x + "px"; this.div.style.top = ne.y + "px"; this.div.style.width = ne.x - sw.x + "px"; this.div.style.height = sw.y - ne.y + "px"; } } /** * The onRemove() method will be called automatically from the API if * we ever set the overlay's map property to 'null'. */ onRemove() { if (this.div) { (this.div.parentNode as HTMLElement).removeChild(this.div); delete this.div; } } /** * Set the visibility to 'hidden' or 'visible'. */ hide() { if (this.div) { this.div.style.visibility = "hidden"; } } show() { if (this.div) { this.div.style.visibility = "visible"; } } toggle() { if (this.div) { if (this.div.style.visibility === "hidden") { this.show(); } else { this.hide(); } } } toggleDOM(map: google.maps.Map) { if (this.getMap()) { this.setMap(null); } else { this.setMap(map); } } } const overlay: USGSOverlay = new USGSOverlay(bounds, image); overlay.setMap(map); const toggleButton = document.createElement("button"); toggleButton.textContent = "Toggle"; toggleButton.classList.add("custom-map-control-button"); const toggleDOMButton = document.createElement("button"); toggleDOMButton.textContent = "Toggle DOM Attachment"; toggleDOMButton.classList.add("custom-map-control-button"); toggleButton.addEventListener("click", () => { overlay.toggle(); }); toggleDOMButton.addEventListener("click", () => { overlay.toggleDOM(map); }); map.controls[google.maps.ControlPosition.TOP_RIGHT].push(toggleDOMButton); map.controls[google.maps.ControlPosition.TOP_RIGHT].push(toggleButton); } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
// This example adds hide() and show() methods to a custom overlay's prototype. // These methods toggle the visibility of the container <div>. // overlay to or from the map. function initMap() { const map = new google.maps.Map(document.getElementById("map"), { zoom: 11, center: { lat: 62.323907, lng: -150.109291 }, mapTypeId: "satellite", }); const bounds = new google.maps.LatLngBounds( new google.maps.LatLng(62.281819, -150.287132), new google.maps.LatLng(62.400471, -150.005608) ); // The photograph is courtesy of the U.S. Geological Survey. let image = "https://developers.google.com/maps/documentation/javascript/"; image += "examples/full/images/talkeetna.png"; /** * The custom USGSOverlay object contains the USGS image, * the bounds of the image, and a reference to the map. */ class USGSOverlay extends google.maps.OverlayView { bounds; image; div; constructor(bounds, image) { super(); this.bounds = bounds; this.image = image; } /** * onAdd is called when the map's panes are ready and the overlay has been * added to the map. */ onAdd() { this.div = document.createElement("div"); this.div.style.borderStyle = "none"; this.div.style.borderWidth = "0px"; this.div.style.position = "absolute"; // Create the img element and attach it to the div. const img = document.createElement("img"); img.src = this.image; img.style.width = "100%"; img.style.height = "100%"; img.style.position = "absolute"; this.div.appendChild(img); // Add the element to the "overlayLayer" pane. const panes = this.getPanes(); panes.overlayLayer.appendChild(this.div); } draw() { // We use the south-west and north-east // coordinates of the overlay to peg it to the correct position and size. // To do this, we need to retrieve the projection from the overlay. const overlayProjection = this.getProjection(); // Retrieve the south-west and north-east coordinates of this overlay // in LatLngs and convert them to pixel coordinates. // We'll use these coordinates to resize the div. const sw = overlayProjection.fromLatLngToDivPixel( this.bounds.getSouthWest() ); const ne = overlayProjection.fromLatLngToDivPixel( this.bounds.getNorthEast() ); // Resize the image's div to fit the indicated dimensions. if (this.div) { this.div.style.left = sw.x + "px"; this.div.style.top = ne.y + "px"; this.div.style.width = ne.x - sw.x + "px"; this.div.style.height = sw.y - ne.y + "px"; } } /** * The onRemove() method will be called automatically from the API if * we ever set the overlay's map property to 'null'. */ onRemove() { if (this.div) { this.div.parentNode.removeChild(this.div); delete this.div; } } /** * Set the visibility to 'hidden' or 'visible'. */ hide() { if (this.div) { this.div.style.visibility = "hidden"; } } show() { if (this.div) { this.div.style.visibility = "visible"; } } toggle() { if (this.div) { if (this.div.style.visibility === "hidden") { this.show(); } else { this.hide(); } } } toggleDOM(map) { if (this.getMap()) { this.setMap(null); } else { this.setMap(map); } } } const overlay = new USGSOverlay(bounds, image); overlay.setMap(map); const toggleButton = document.createElement("button"); toggleButton.textContent = "Toggle"; toggleButton.classList.add("custom-map-control-button"); const toggleDOMButton = document.createElement("button"); toggleDOMButton.textContent = "Toggle DOM Attachment"; toggleDOMButton.classList.add("custom-map-control-button"); toggleButton.addEventListener("click", () => { overlay.toggle(); }); toggleDOMButton.addEventListener("click", () => { overlay.toggleDOM(map); }); map.controls[google.maps.ControlPosition.TOP_RIGHT].push(toggleDOMButton); map.controls[google.maps.ControlPosition.TOP_RIGHT].push(toggleButton); } window.initMap = initMap;
CSS
/* * Always set the map height explicitly to define the size of the div element * that contains the map. */ #map { height: 100%; } /* * Optional: Makes the sample page fill the window. */ html, body { height: 100%; margin: 0; padding: 0; } .custom-map-control-button { background-color: #fff; border: 0; border-radius: 2px; box-shadow: 0 1px 4px -1px rgba(0, 0, 0, 0.3); margin: 10px; padding: 0 0.5em; font: 400 18px Roboto, Arial, sans-serif; overflow: hidden; height: 40px; cursor: pointer; } .custom-map-control-button:hover { background: rgb(235, 235, 235); }
HTML
<html> <head> <title>Showing/Hiding Overlays</title> <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script> <link rel="stylesheet" type="text/css" href="./style.css" /> <script type="module" src="./index.js"></script> </head> <body> <div id="map"></div> <!-- The `defer` attribute causes the callback to execute after the full HTML document has been parsed. For non-blocking uses, avoiding race conditions, and consistent behavior across browsers, consider loading using Promises. See https://developers.google.com/maps/documentation/javascript/load-maps-js-api for more information. --> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly" defer ></script> </body> </html>