Maps JavaScript API는 래스터와 벡터의 두 가지 지도 구현 방법을 제공합니다. 래스터 지도는 지도 이미지를 Google 지도 플랫폼 서버 측에서 생성한 후 웹 앱에 제공하는 픽셀 기반 래스터 이미지 타일의 그리드로 로드합니다. 벡터 지도는 벡터 기반 타일로 구성되며, 이러한 타일은 브라우저가 사용자 기기의 GPU에 액세스하여 2D 및 3D 그래픽을 렌더링할 수 있는 웹 기술인 WebGL을 사용하여 클라이언트 측의 로드 시간에 그려집니다.
벡터 지도는 사용자에게 익숙한 Google 지도와 같으며 기본 래스터 타일 지도에 비해 벡터 기반 이미지의 선명도, 가까운 확대/축소 수준에서 3D 빌딩 추가 등의 여러 가지 장점을 제공합니다. 벡터 지도는 다음 기능을 지원합니다.
- 프로그래매틱 기울기 및 방향 제어
- 향상된 카메라 제어
- 더욱 원활한 확대/축소를 위한 부분 확대/축소
div
요소와 JavaScript를 사용하여 로드된 지도의 기본 렌더링 유형은google.maps.RenderingType.RASTER
입니다.gmp-map
요소를 사용하여 로드된 지도의 기본 렌더링 유형은 틸트 및 방향 컨트롤이 사용 설정된google.maps.RenderingType.VECTOR
입니다.
기울기 및 회전
지도를 초기화할 때 heading
및 tilt
속성을 포함하고 지도에서 setTilt
및 setHeading
메서드를 호출하여 벡터 지도에서 기울기 및 회전(방향)을 설정할 수 있습니다. 다음 예에서는 지도에 기울기 및 방향을 프로그래매틱 방식으로 20도씩 조정하는 버튼을 추가합니다.
TypeScript
function initMap(): void { const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { center: { lat: 37.7893719, lng: -122.3942, }, zoom: 16, heading: 320, tilt: 47.5, mapId: "90f87356969d889c", } ); const buttons: [string, string, number, google.maps.ControlPosition][] = [ ["Rotate Left", "rotate", 20, google.maps.ControlPosition.LEFT_CENTER], ["Rotate Right", "rotate", -20, google.maps.ControlPosition.RIGHT_CENTER], ["Tilt Down", "tilt", 20, google.maps.ControlPosition.TOP_CENTER], ["Tilt Up", "tilt", -20, google.maps.ControlPosition.BOTTOM_CENTER], ]; buttons.forEach(([text, mode, amount, position]) => { const controlDiv = document.createElement("div"); const controlUI = document.createElement("button"); controlUI.classList.add("ui-button"); controlUI.innerText = `${text}`; controlUI.addEventListener("click", () => { adjustMap(mode, amount); }); controlDiv.appendChild(controlUI); map.controls[position].push(controlDiv); }); const adjustMap = function (mode: string, amount: number) { switch (mode) { case "tilt": map.setTilt(map.getTilt()! + amount); break; case "rotate": map.setHeading(map.getHeading()! + amount); break; default: break; } }; } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
function initMap() { const map = new google.maps.Map(document.getElementById("map"), { center: { lat: 37.7893719, lng: -122.3942, }, zoom: 16, heading: 320, tilt: 47.5, mapId: "90f87356969d889c", }); const buttons = [ ["Rotate Left", "rotate", 20, google.maps.ControlPosition.LEFT_CENTER], ["Rotate Right", "rotate", -20, google.maps.ControlPosition.RIGHT_CENTER], ["Tilt Down", "tilt", 20, google.maps.ControlPosition.TOP_CENTER], ["Tilt Up", "tilt", -20, google.maps.ControlPosition.BOTTOM_CENTER], ]; buttons.forEach(([text, mode, amount, position]) => { const controlDiv = document.createElement("div"); const controlUI = document.createElement("button"); controlUI.classList.add("ui-button"); controlUI.innerText = `${text}`; controlUI.addEventListener("click", () => { adjustMap(mode, amount); }); controlDiv.appendChild(controlUI); map.controls[position].push(controlDiv); }); const adjustMap = function (mode, amount) { switch (mode) { case "tilt": map.setTilt(map.getTilt() + amount); break; case "rotate": map.setHeading(map.getHeading() + amount); break; default: break; } }; } 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; } .ui-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; } .ui-button:hover { background: rgb(235, 235, 235); }
HTML
<html> <head> <title>Tilt and Rotation</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>
샘플 사용해 보기
마우스 및 키보드 동작 사용
기울기 및 회전(방향) 사용자 상호작용이 프로그래매틱 방식으로 또는 Google Cloud 콘솔에서 사용 설정된 경우 사용자는 마우스와 키보드를 사용하여 기울기와 회전을 조정할 수 있습니다.
- 마우스 사용: Shift 키를 누른 상태에서 마우스를 클릭하고 위아래로 드래그하여 기울기를 조정하고, 좌우로 드래그하여 방향을 조정합니다.
- 키보드 사용: Shift 키를 누른 상태에서 위쪽 및 아래쪽 화살표 키를 사용하여 기울기를 조정하고 오른쪽 및 왼쪽 화살표 키를 사용하여 방향을 조정합니다.
프로그래매틱 방식으로 기울기 및 방향 조정
setTilt()
및 setHeading()
메서드를 사용하여 벡터 지도에서 기울기 및 방향을 프로그래매틱 방식으로 조정합니다. 방향은 카메라가 북쪽에서 시작하여 시계 방향으로 가리키는 방향이므로 map.setHeading(90)
은 동쪽이 위를 향하도록 지도를 회전합니다. 기울기 각도는 천정에서부터 측정되므로 map.setTilt(0)
은 똑바로 아래를 가리키고 map.setTilt(45)
는 비스듬하게 가리킵니다.
- 지도의 기울기 각도를 설정하려면
setTilt()
를 호출합니다. 현재 기울기 값을 가져오려면getTilt()
를 사용합니다. - 지도의 방향을 설정하려면
setHeading()
을 호출합니다. 현재 방향 값을 가져오려면getHeading()
을 사용합니다.
기울기와 방향을 유지하면서 지도 중심을 변경하려면 map.setCenter()
또는 map.panBy()
를 사용하세요.
사용할 수 있는 각도 범위는 현재 확대/축소 수준에 따라 다릅니다. 이 범위를 벗어나는 값은 현재 허용되는 범위로 고정됩니다.
moveCamera
메서드를 사용하여 방향, 기울기, 중심, 확대/축소를 프로그래매틱 방식으로 변경할 수도 있습니다. 자세히 알아보기
다른 메서드에 미치는 영향
지도에 기울기 또는 회전이 적용되면 다른 Maps JavaScript API 메서드의 동작이 영향을 받습니다.
map.getBounds()
는 항상 표시되는 지역이 포함된 가장 작은 경계 상자를 반환합니다. 기울기가 적용되면 반환된 경계가 지도 표시 영역의 표시된 영역보다 더 큰 지역을 나타낼 수도 있습니다.map.fitBounds()
는 경계에 맞추기 전에 기울기 및 방향을 0으로 재설정합니다.map.panToBounds()
는 경계를 이동하기 전에 기울기 및 방향을 0으로 재설정합니다.map.setTilt()
는 모든 값을 허용하지만 현재 지도의 확대/축소 수준에 따라 최대 기울기를 제한합니다.map.setHeading()
은 모든 값을 허용하며 [0, 360] 범위에 맞게 수정합니다.
카메라 제어하기
map.moveCamera()
함수를 사용하여 카메라 속성의 조합을 한 번에 업데이트할 수 있습니다. map.moveCamera()
는 업데이트할 모든 카메라 속성이 포함된 단일 매개변수를 허용합니다. 다음 예는 map.moveCamera()
를 호출하여 center
, zoom
, heading
, tilt
를 한 번에 설정하는 방법을 보여줍니다.
map.moveCamera({
center: new google.maps.LatLng(37.7893719, -122.3942),
zoom: 16,
heading: 320,
tilt: 47.5
});
다음과 같이 애니메이션 루프로 map.moveCamera()
를 호출하여 카메라 속성에 애니메이션을 적용할 수 있습니다.
const degreesPerSecond = 3;
function animateCamera(time) {
// Update the heading, leave everything else as-is.
map.moveCamera({
heading: (time / 1000) * degreesPerSecond
});
requestAnimationFrame(animateCamera);
}
// Start the animation.
requestAnimationFrame(animateCamera);
카메라 위치
지도뷰는 평면을 내려다보는 카메라로 모델링됩니다. 카메라의 위치(및 이에 따른 지도의 렌더링)는 타겟(위도/경도 위치), 방위, 기울기, 확대/축소 속성으로 지정됩니다.
타겟(위치)
카메라 타겟은 지도 중앙의 위치에 해당되며 위도와 경도 좌표로 지정됩니다.
위도는 -85도 이상 85도 이하로 설정할 수 있습니다. 이 범위보다 크거나 작은 값은 범위 내의 가장 가까운 값으로 고정됩니다. 예를 들어 위도를 100으로 지정하면 값이 85로 설정됩니다. 경도는 -180도 이상 180도 이하로 설정할 수 있습니다. 이 범위보다 크거나 작은 값은 범위(-180, 180) 내에 속하도록 조정됩니다. 예를 들어 480, 840, 1,200은 120도로 조정됩니다.방위(방향)
카메라 방위는 나침반 방향을 지정하며, 지도의 상단 가장자리에 해당하는 진북에서부터 측정됩니다(단위: 도). 지도의 중앙에서 지도의 상단 가장자리까지 수직선을 그렸을 때 진북을 기준으로 한 카메라의 방향(단위: 도)이 방위에 해당합니다.
방위가 0이면 지도 상단이 진북을 가리킵니다. 방위 값이 90이면 지도 상단이 정동을 가리킵니다(나침반의 90도). 값이 180이면 지도 상단이 정남을 가리킵니다.
지도 API를 사용하면 지도의 방위를 변경할 수 있습니다. 예를 들어 차량 운전자는 도로 지도를 돌려서 자신의 이동 방향에 맞출 때가 많은 반면, 지도와 나침반을 사용하는 도보 여행자는 대체로 수직선이 북쪽을 향하도록 지도의 방향을 바꿉니다.
기울기(시야각)
기울기는 지도의 중앙 지점 바로 위에 있는 원호상에서 카메라 위치를 정의하며 천저(카메라 바로 아래를 가리키는 방향)에서부터 측정됩니다(단위: 도). 0은 수직으로 아래를 가리키는 카메라에 해당합니다. 0보다 큰 값은 지정된 각도로 지평선을 향해 기울어진 카메라에 해당합니다. 시야각을 변경하면 지도가 원근법으로 표시되어 멀리 있는 지형지물은 더 작게 표시되고 가까이 있는 지형지물은 더 크게 표시됩니다. 다음 그림은 이러한 원근법을 보여줍니다.
아래 이미지에서 시야각은 0도입니다. 첫 번째 이미지는 이를 개략적으로 보여줍니다. 위치 1은 카메라 위치, 위치 2는 현재 지도의 위치에 해당합니다. 그 결과 나타나는 지도는 아래와 같습니다.
아래 이미지에서 시야각은 45도입니다. 카메라는 바로 위(0도)와 지상(90도) 사이의 원호를 따라 위치 3으로 절반쯤 이동합니다. 카메라는 여전히 지도의 중심점을 가리키지만 이제 위치 4에서 선으로 표시되는 영역이 보입니다.
이 스크린샷에서 지도의 중앙은 원래 지도와 동일한 지점에 중심이 맞추어져 있지만 지도 상단에서는 더 많은 지형지물이 표시되어 있습니다. 시야각을 45도 이상으로 올리면 카메라와 지도 위치 사이의 지형지물이 그에 비례하여 크게 표시되는 반면, 지도 위치 너머에 있는 지형지물은 그에 비례하여 작게 표시되어 입체적 효과를 줍니다.
확대/축소
카메라의 확대/축소 수준이 지도의 축척을 결정합니다. 확대/축소 수준이 높을수록 더욱 상세한 화면을 볼 수 있는 반면, 확대/축소 수준이 낮을수록 더 넓은 영역을 화면에 표시할 수 있습니다.
확대/축소 수준은 정수가 아니어도 됩니다. 지도에서 허용되는 확대/축소 수준의 범위는 대상, 지도 유형, 화면 크기 등 여러 가지 요소에 따라 달라집니다. 범위를 벗어난 모든 숫자는 그 다음으로 유효한 근사치로 변환됩니다. 이 값은 최소 확대/축소 수준 또는 최대 확대/축소 수준일 수 있습니다. 다음 목록은 각 확대/축소 수준에서 기대할 수 있는 세밀한 정도의 대략적인 수준을 보여줍니다.
- 1: 세계
- 5: 대륙
- 10: 도시
- 15: 거리
- 20: 건물
부분 확대/축소
벡터 지도는 정수 대신 분수 값을 사용하는 부분 확대/축소를 지원합니다. 래스터 지도와 벡터 지도 모두 부분 확대/축소를 지원하지만 벡터 지도의 경우 부분 확대/축소가 기본적으로 사용 설정되고 래스터 지도의 경우 기본적으로 사용 중지됩니다. 부분 확대/축소를 사용 설정하거나 중지하려면 isFractionalZoomEnabled
지도 옵션을 사용하세요.
다음 예는 지도를 초기화할 때 부분 확대/축소를 사용 설정하는 방법을 보여줍니다.
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -34.397, lng: 150.644},
zoom: 8,
isFractionalZoomEnabled: true
});
아래와 같이 isFractionalZoomEnabled
지도 옵션을 설정하여 부분 확대/축소를 사용 설정하거나 중지할 수도 있습니다.
// Using map.set
map.set('isFractionalZoomEnabled', true);
// Using map.setOptions
map.setOptions({isFractionalZoomEnabled: true});
리스너를 설정하여 부분 확대/축소가 사용 설정되어 있는지 감지할 수 있습니다. 이는 isFractionalZoomEnabled
를 true
또는 false
로 명시적으로 설정하지 않은 경우에 가장 유용합니다. 다음 예시 코드에서는 부분 확대/축소가 사용 설정되어 있는지 확인합니다.
map.addListener('isfractionalzoomenabled_changed', () => {
const isFractionalZoomEnabled = map.get('isFractionalZoomEnabled');
if (isFractionalZoomEnabled === false) {
console.log('not using fractional zoom');
} else if (isFractionalZoomEnabled === true) {
console.log('using fractional zoom');
} else {
console.log('map not done initializing yet');
}
});