이 페이지에서는 수신 대기하고 프로그래매틱 방식으로 처리할 수 있는 사용자 인터페이스 이벤트와 오류 이벤트를 설명합니다.
사용자 인터페이스 이벤트
브라우저 내의 JavaScript는 이벤트 구동 방식으로 작동합니다. 즉 JavaScript는 이벤트를 생성하여 상호작용에 응답하고, 프로그램이 관심 있는 이벤트를 수신 대기할 것으로 예상합니다. 두 가지 유형의 이벤트가 있습니다.
- 사용자 이벤트(예: '클릭' 마우스 이벤트)는 DOM에서 Maps JavaScript API로 전달됩니다. 이러한 이벤트는 표준 DOM 이벤트와 별개이며 서로 구분됩니다.
- MVC 상태 변경 알림에는 Maps JavaScript API 객체의 변경사항이 반영되며
property_changed
규칙을 사용하여 이름이 지정됩니다.
각 Maps JavaScript API 객체는 여러 개의 이름이 지정된 이벤트를 내보냅니다.
특정 이벤트에 관심이 있는 프로그램에서는 해당 이벤트에 대한 JavaScript 이벤트 리스너를 등록하고 addListener()
를 호출하여 이벤트가 수신되면 객체에 이벤트 핸들러를 등록하여 코드를 실행합니다.
다음 샘플은 앱과 상호작용할 때 google.maps.Map
에 의해 트리거되는 이벤트를 보여줍니다.
이벤트의 전체 목록은 Maps JavaScript API 참조를 참고하세요. 이벤트는 이벤트가 포함된 객체별로 별도 섹션에 나열되어 있습니다.
UI 이벤트
Maps JavaScript API 내의 일부 객체는 마우스 또는 키보드 이벤트와 같은 사용자 이벤트에 응답하도록 디자인되었습니다. 예를 들어 다음은 google.maps.marker.AdvancedMarkerElement
객체가 수신 대기할 수 있는 사용자 이벤트입니다.
'click'
'drag'
'dragend'
'dragstart'
'gmp-click'
전체 목록은 AdvancedMarkerElement 클래스를 참고하세요. 이러한 이벤트는 표준 DOM 이벤트처럼 보일 수도 있지만 실제로는 Maps JavaScript API의 일부입니다. 브라우저마다 다른 DOM 이벤트 모델을 구현하므로 Maps JavaScript API에서는 다양한 교차 브라우저 특성을 처리할 필요 없이 DOM 이벤트를 수신 대기하고 이에 응답하는 메커니즘을 제공합니다. 또한 이러한 이벤트는 대개 이벤트 내에서 UI 상태(예: 마우스 위치)를 나타내는 인수를 전달합니다.
MVC 상태 변경사항
MVC 객체에는 대개 상태가 포함됩니다. 객체의 속성이 변경될 때마다 Maps JavaScript API는 속성이 변경된 이벤트를 실행합니다.
예를 들어 지도의 확대/축소 레벨이 변경되면 API가 지도에서 zoom_changed
이벤트를 실행합니다. addListener()
를 호출하여 객체에 이벤트 핸들러를 등록하여 이러한 상태 변경사항을 가로챌 수도 있습니다.
사용자 이벤트와 MVC 상태 변경사항은 비슷해 보일 수도 있지만 일반적으로 코드에서 다르게 취급하고 싶을 수 있습니다. 예를 들어 MVC 이벤트는 이벤트 내에 인수를 전달하지 않습니다. 해당 객체에 대해 적절한 getProperty
메서드를 호출하여 MVC 상태 변경사항에서 변경된 속성을 검사하고 싶을 수 있습니다.
이벤트 처리
이벤트 알림을 등록하려면 addListener()
이벤트 핸들러를 사용하세요. 이 메서드는 수신 대기할 이벤트, 지정된 이벤트가 발생할 때 호출할 함수를 취합니다.
예: 지도 및 마커 이벤트
다음 코드는 사용자 이벤트를 상태 변경 이벤트와 혼합합니다. 클릭될 때 지도를 확대/축소하는 마커에 이벤트 핸들러를 연결힙니다. 또한 center
속성의 변경사항을 위한 이벤트 핸들러를 지도에 추가하고 center_changed
이벤트가 수신된 지 3초 후 지도를 마커로 다시 화면 이동합니다.
TypeScript
async function initMap() { // Request needed libraries. const { Map } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary; const { AdvancedMarkerElement } = await google.maps.importLibrary("marker") as google.maps.MarkerLibrary; const myLatlng = { lat: -25.363, lng: 131.044 }; const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { zoom: 4, center: myLatlng, mapId: "DEMO_MAP_ID", } ); const marker = new google.maps.marker.AdvancedMarkerElement({ position: myLatlng, map, title: "Click to zoom", }); map.addListener("center_changed", () => { // 3 seconds after the center of the map has changed, pan back to the // marker. window.setTimeout(() => { map.panTo(marker.position as google.maps.LatLng); }, 3000); }); marker.addListener("click", () => { map.setZoom(8); map.setCenter(marker.position as google.maps.LatLng); }); } initMap();
JavaScript
async function initMap() { // Request needed libraries. const { Map } = await google.maps.importLibrary("maps"); const { AdvancedMarkerElement } = await google.maps.importLibrary("marker"); const myLatlng = { lat: -25.363, lng: 131.044 }; const map = new google.maps.Map(document.getElementById("map"), { zoom: 4, center: myLatlng, mapId: "DEMO_MAP_ID", }); const marker = new google.maps.marker.AdvancedMarkerElement({ position: myLatlng, map, title: "Click to zoom", }); map.addListener("center_changed", () => { // 3 seconds after the center of the map has changed, pan back to the // marker. window.setTimeout(() => { map.panTo(marker.position); }, 3000); }); marker.addListener("click", () => { map.setZoom(8); map.setCenter(marker.position); }); } initMap();
샘플 사용해 보기
팁: 표시 영역의 변경을 감지하려면 구성요소인 zoom_changed
및 center_changed
이벤트가 아니라 특정 bounds_changed
이벤트를 사용해야 합니다. Maps JavaScript API는 후자의 이벤트를 독립적으로 실행하므로 표시 영역이 정식으로 변경될 때까지는 getBounds()
에서 유용한 결과를 보고하지 않을 수도 있습니다. 이러한 이벤트 후에 getBounds()
를 실행하려면 대신 bounds_changed
이벤트를 수신 대기해야 합니다.
예: 도형 수정 및 드래그 이벤트
도형이 수정되거나 드래그되면 액션 완료 시 이벤트가 실행됩니다. 이벤트와 코드 스니펫의 목록은 도형을 참고하세요.
UI 이벤트에서 인수 액세스
Maps JavaScript API 내 UI 이벤트는 일반적으로 이벤트가 발생했을 때 UI 상태를 나타내는 이벤트 인수를 전달하며, 이 인수는 이벤트 리스너에서 액세스할 수 있습니다. 예를 들어 UI 'click'
이벤트는 일반적으로 지도의 클릭된 위치를 나타내는 latLng
속성이 포함된 MouseEvent
를 전달합니다. 이 동작은 UI 이벤트에만 해당합니다. MVC 상태 변경은 이벤트에 인수를 전달하지 않습니다.
객체의 속성에 액세스하는 것과 동일한 방식으로 이벤트 리스너 내에서 이벤트의 인수에 액세스할 수 있습니다. 다음 예에서는 지도를 위한 이벤트 리스너를 추가하고 사용자가 클릭된 위치에서 지도를 클릭할 때 마커를 만듭니다.
TypeScript
async function initMap() { // Request needed libraries. const { Map } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary; const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary("marker") as google.maps.MarkerLibrary; const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { zoom: 4, center: { lat: -25.363882, lng: 131.044922 }, mapId: "DEMO_MAP_ID", } ); map.addListener("click", (e) => { placeMarkerAndPanTo(e.latLng, map); }); } function placeMarkerAndPanTo(latLng: google.maps.LatLng, map: google.maps.Map) { new google.maps.marker.AdvancedMarkerElement({ position: latLng, map: map, }); map.panTo(latLng); } initMap();
JavaScript
async function initMap() { // Request needed libraries. const { Map } = await google.maps.importLibrary("maps"); const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary( "marker", ); const map = new google.maps.Map(document.getElementById("map"), { zoom: 4, center: { lat: -25.363882, lng: 131.044922 }, mapId: "DEMO_MAP_ID", }); map.addListener("click", (e) => { placeMarkerAndPanTo(e.latLng, map); }); } function placeMarkerAndPanTo(latLng, map) { new google.maps.marker.AdvancedMarkerElement({ position: latLng, map: map, }); map.panTo(latLng); } initMap();
샘플 사용해 보기
이벤트 리스너에서 클로저 사용
이벤트 리스너를 실행할 때 객체에 비공개 데이터와 영구 데이터를 모두 연결하는 것이 유용한 경우가 많습니다. JavaScript는 '비공개' 인스턴스 데이터를 지원하지 않지만 내부 함수에서 외부 변수에 액세스할 수 있도록 해 주는 클로저를 지원합니다. 클로저는 이벤트 리스너 내에서 일반적으로 이벤트가 발생하는 객체에 연결되지 않는 변수에 액세스하는 데 유용합니다.
다음 예에서는 이벤트 리스너의 함수 클로저를 사용하여 마커 집합에 비밀 메시지를 할당합니다. 각 마커를 클릭하면 마커 자체에 포함되지 않은 비밀 메시지의 부분이 표시됩니다.
TypeScript
async function initMap() { // Request needed libraries. const { Map } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary; const { AdvancedMarkerElement } = await google.maps.importLibrary("marker") as google.maps.MarkerLibrary; const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { zoom: 4, center: { lat: -25.363882, lng: 131.044922 }, mapId: "DEMO_MAP_ID", } ); const bounds: google.maps.LatLngBoundsLiteral = { north: -25.363882, south: -31.203405, east: 131.044922, west: 125.244141, }; // Display the area between the location southWest and northEast. map.fitBounds(bounds); // Add 5 markers to map at random locations. // For each of these markers, give them a title with their index, and when // they are clicked they should open an infowindow with text from a secret // message. const secretMessages = ["This", "is", "the", "secret", "message"]; const lngSpan = bounds.east - bounds.west; const latSpan = bounds.north - bounds.south; for (let i = 0; i < secretMessages.length; ++i) { const marker = new google.maps.marker.AdvancedMarkerElement({ position: { lat: bounds.south + latSpan * Math.random(), lng: bounds.west + lngSpan * Math.random(), }, map: map, }); attachSecretMessage(marker, secretMessages[i]); } } // Attaches an info window to a marker with the provided message. When the // marker is clicked, the info window will open with the secret message. function attachSecretMessage( marker: google.maps.marker.AdvancedMarkerElement, secretMessage: string ) { const infowindow = new google.maps.InfoWindow({ content: secretMessage, }); marker.addListener("click", () => { infowindow.open(marker.map, marker); }); } initMap();
JavaScript
async function initMap() { // Request needed libraries. const { Map } = await google.maps.importLibrary("maps"); const { AdvancedMarkerElement } = await google.maps.importLibrary("marker"); const map = new google.maps.Map(document.getElementById("map"), { zoom: 4, center: { lat: -25.363882, lng: 131.044922 }, mapId: "DEMO_MAP_ID", }); const bounds = { north: -25.363882, south: -31.203405, east: 131.044922, west: 125.244141, }; // Display the area between the location southWest and northEast. map.fitBounds(bounds); // Add 5 markers to map at random locations. // For each of these markers, give them a title with their index, and when // they are clicked they should open an infowindow with text from a secret // message. const secretMessages = ["This", "is", "the", "secret", "message"]; const lngSpan = bounds.east - bounds.west; const latSpan = bounds.north - bounds.south; for (let i = 0; i < secretMessages.length; ++i) { const marker = new google.maps.marker.AdvancedMarkerElement({ position: { lat: bounds.south + latSpan * Math.random(), lng: bounds.west + lngSpan * Math.random(), }, map: map, }); attachSecretMessage(marker, secretMessages[i]); } } // Attaches an info window to a marker with the provided message. When the // marker is clicked, the info window will open with the secret message. function attachSecretMessage(marker, secretMessage) { const infowindow = new google.maps.InfoWindow({ content: secretMessage, }); marker.addListener("click", () => { infowindow.open(marker.map, marker); }); } initMap();
샘플 사용해 보기
이벤트 핸들러 내에서 속성 가져오기 및 설정
Maps JavaScript API 이벤트 시스템의 어느 MVC 상태 변경 이벤트도 이벤트가 트리거될 때 인수를 전달하지 않습니다. (사용자 이벤트는 검사할 수 있는 인수를 전달합니다.) MVC 상태 변경사항의 속성을 검사해야 하는 경우 해당 객체에서 적절한 getProperty()
메서드를 명시적으로 호출해야 합니다. 이 검사에서는 항상 MVC 객체의 현재 상태를 가져오며 이 상태는 이벤트가 처음 실행된 때의 상태가 아닐 수도 있습니다.
참고: 해당 특정 속성의 상태 변경에 응답하는 이벤트 핸들러 내에서 속성을 명시적으로 설정하면 예기치 않거나 원치 않는 동작이 발생할 수도 있습니다. 예를 들어 이러한 속성을 설정하면 새 이벤트가 트리거됩니다. 항상 이 이벤트 핸들러 내에서 속성을 설정하면 무한 루프가 생성될 수도 있습니다.
아래 예시에서는 해당 수준을 표시하는 정보 창을 표시하여 확대/축소 이벤트에 응답하도록 이벤트 핸들러를 설정합니다.
TypeScript
async function initMap() { // Request needed libraries. const { Map } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary; const originalMapCenter = new google.maps.LatLng(-25.363882, 131.044922); const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { zoom: 4, center: originalMapCenter, } ); const infowindow = new google.maps.InfoWindow({ content: "Change the zoom level", position: originalMapCenter, }); infowindow.open(map); map.addListener("zoom_changed", () => { infowindow.setContent("Zoom: " + map.getZoom()!); }); } initMap();
JavaScript
async function initMap() { // Request needed libraries. const { Map } = await google.maps.importLibrary("maps"); const originalMapCenter = new google.maps.LatLng(-25.363882, 131.044922); const map = new google.maps.Map(document.getElementById("map"), { zoom: 4, center: originalMapCenter, }); const infowindow = new google.maps.InfoWindow({ content: "Change the zoom level", position: originalMapCenter, }); infowindow.open(map); map.addListener("zoom_changed", () => { infowindow.setContent("Zoom: " + map.getZoom()); }); } initMap();
샘플 사용해 보기
DOM 이벤트 수신 대기
Maps JavaScript API 이벤트 모델은 자체 맞춤 이벤트를 만들고 관리합니다. 하지만 브라우저 내의 DOM(문서 객체 모델)도 사용 중인 특정 브라우저 이벤트 모델에 따라 자체 이벤트를 만들고 전달합니다. 이러한 이벤트를 캡처하고 이에 응답하려는 경우 Maps JavaScript API에서 addDomListener()
정적 메서드를 제공하여 DOM 이벤트를 수신 대기하고 이에 바인딩합니다.
이 편리한 메서드에는 아래와 같은 서명이 있습니다.
addDomListener(instance:Object, eventName:string, handler:Function)
여기에서 instance
는 다음을 비롯하여 브라우저에서 지원하는 DOM 요소입니다.
- DOM의 계층적 구성요소(예:
window
또는document.body.myform
) - 이름이 지정된 요소(예:
document.getElementById("foo")
)
addDomListener()
는 지정된 이벤트를 브라우저에 전달하며 브라우저에서 브라우저의 DOM 이벤트 모델에 따라 이벤트를 처리합니다. 하지만 거의 모든 최신 브라우저가 DOM 수준 2 이상을 지원합니다. DOM 수준 이벤트에 대한 자세한 내용은 Mozilla DOM 수준 참조를 참고하세요.
TypeScript
async function initMap() { // Request needed libraries. const { Map } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary; const mapDiv = document.getElementById("map") as HTMLElement; const map = new google.maps.Map(mapDiv, { zoom: 8, center: new google.maps.LatLng(-34.397, 150.644), }); // We add a DOM event here to show an alert if the DIV containing the // map is clicked. google.maps.event.addDomListener(mapDiv, "click", () => { window.alert("Map was clicked!"); }); } initMap();
JavaScript
async function initMap() { // Request needed libraries. const { Map } = await google.maps.importLibrary("maps"); const mapDiv = document.getElementById("map"); const map = new google.maps.Map(mapDiv, { zoom: 8, center: new google.maps.LatLng(-34.397, 150.644), }); // We add a DOM event here to show an alert if the DIV containing the // map is clicked. google.maps.event.addDomListener(mapDiv, "click", () => { window.alert("Map was clicked!"); }); } initMap();
HTML
<html> <head> <title>Listening to DOM Events</title> <link rel="stylesheet" type="text/css" href="./style.css" /> <script type="module" src="./index.js"></script> </head> <body> <div id="map"></div> <!-- prettier-ignore --> <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))}) ({key: "AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg", v: "weekly"});</script> </body> </html>
샘플 사용해 보기
위의 코드는 Maps JavaScript API 코드이지만 addDomListener()
메서드가 브라우저의 window
객체에 바인딩되어 API가 API의 일반 도메인 외부에 있는 객체와 통신할 수 있도록 허용합니다.
이벤트 리스너 삭제
특정 이벤트 리스너를 삭제하려면 리스너가 변수에 할당되어 있어야 합니다. 그런 다음 removeListener()
를 호출하여 리스너가 할당된 변수 이름을 전달할 수 있습니다.
var listener1 = marker.addListener('click', aFunction); google.maps.event.removeListener(listener1);
특정 인스턴스에서 모든 리스너를 삭제하려면 clearInstanceListeners()
를 호출하여 인스턴스 이름을 전달하세요.
var listener1 = marker.addListener('click', aFunction); var listener2 = marker.addListener('mouseover', bFunction); // Remove listener1 and listener2 from marker instance. google.maps.event.clearInstanceListeners(marker);
특정 인스턴스의 특정 이벤트 유형에 대한 리스너를 모두 삭제하려면 clearListeners()
를 호출하여 인스턴스 이름과 이벤트 이름을 전달하세요.
marker.addListener('click', aFunction); marker.addListener('click', bFunction); marker.addListener('click', cFunction); // Remove all click listeners from marker instance. google.maps.event.clearListeners(marker, 'click');
자세한 내용은 google.maps.event 네임스페이스 참조 문서를 참고하세요.
인증 오류 수신 대기
인증 실패를 프로그래매틱 방식으로 감지하려면(예: 비콘을 자동으로 전송하기 위해) 콜백 함수를 준비하세요.
다음 전역 함수가 정의된 경우 인증 실패 시 함수가 호출됩니다.
function gm_authFailure() { /* Code */ };