บทนำ
การวางซ้อนคือออบเจ็กต์บนแผนที่ที่เชื่อมโยงกับพิกัดละติจูด/ลองจิจูด จึงจะเลื่อนเมื่อคุณลากหรือซูมแผนที่ ดูข้อมูลเกี่ยวกับประเภทการซ้อนทับที่กำหนดไว้ล่วงหน้าได้ที่การวาดบนแผนที่
Maps JavaScript API มีคลาส
OverlayView สำหรับ
สร้างการวางซ้อนที่กำหนดเอง OverlayView เป็นคลาสพื้นฐานที่
มีเมธอดหลายอย่างที่คุณต้องใช้เมื่อสร้างการซ้อนทับ นอกจากนี้ คลาสยังมีเมธอดบางอย่างที่ช่วยให้สามารถแปลระหว่างพิกัดบนหน้าจอและตำแหน่งบนแผนที่ได้
เพิ่มการซ้อนทับที่กำหนดเอง
สรุปขั้นตอนที่ต้องทำเพื่อสร้างการซ้อนทับที่กำหนดเองมีดังนี้
- ตั้งค่า 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> แล้วแนบภาพซ้อนทับกับ pane ของแผนที่ บานหน้าต่าง
คือโหนดภายในแผนผัง 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>
    <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 script 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>