구글 맵

홈으로

경주 남산, 삼릉 가는길

맵 작성하기

구글맵 작성하기
1. 먼저, html 문서에서 지도를 보관할 가칭 map 이라는 <div> 요소를 만들고(<div id="map"> .. </div>), Css에서 이 맵 영역 <div> 요소의 크기(height)를 지정해준다(#map { height: 100%; }). 이어서, Maps JavaScript API 로드를 써서 Maps JavaScript API를 로드해준다:
[ 구글맵 작성의 기본 ]
                                        
                                            
                                        
                                    
                                        
                                            /* 빈 div 요소의 높이는 0이므로 맵 div에는 반드시 높이를 명시해주어야 한다! */
                                            #map { height: 100%; }
                                        
                                    

전체 페이지로 맵을 표시할 때는 html, body { height: 100%; margin: 0 auto; padding: 0; }와 같은 방식으로 추가 설정해준다!

                                        
                                            <!-- Maps JavaScript API 로드 -->
                                            <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: "Get your API key", v: "weekly" });
                                            </script>
                                        
                                    

key는 필수이고, v 옵션에는 alpha(테스트를 위한 개발자 전용판), beta(주간 추가 변경사항 포함), weekly(기본값: 주간 업데이트판), quarterly(분기별 업데이트판) 등을 넣어줄 수 있다 API key(및 mapId)를 구하려면; Get your API key 로 가보십시오..

2. 다음으로, async .. await 함수 안에서 importLibrary()Map 클래스를 로드하고, new 연산자를 써서 Map 객체를 만들어 초기화해준다:
[ 구글맵 라이브러리 불러오기 및 Map 객체 초기화 ]
                                        
                                            async function initMap() {
                                                let map;

                                                const position= { lat: 35.79809, lng: 129.20654 }; // 지도 위치 설정
                                                const zoom= 15 // 줌 설정 ← 1(지구)/5(대륙)/10(도시)/15(거리)/20(건물)

                                                /* 맵 라이브러리 불러오기 */
                                                const { Map } = await google.maps.importLibrary("maps");

                                                /* 맵 객체의 인스턴스 생성하기 */
                                                map= new Map(document.getElementById("map"), { 
                                                    center: position, // 지도 중심 위치 설정
                                                    zoom: zoom, // 확대/축소 줌 설정
                                                    mapId: "DEMO_MAP_ID", // 맵 ID ← 테스트용일 때는 "DEMO_MAP_ID"를 사용하면 된다!
                                                });
                                            }
                                    
                                            initMap()
                                        
                                    

위치를 표시하는 center는 [구글지도] 특정 위치의 마우스 우측버튼 메뉴에서 "이곳이 궁금한가요?"를 눌러서 확인할 수 있다!

3. 맵 고급 마커를 정의하려면; 먼저 AdvancedMarkerElement(및 PinElement) 클래스를 제공하는 marker 라이브러리를 로드해야 한다:
[ 구글맵 마커 설정 ]
                                        
                                            async function initMap() {
                                                ..

                                                /* 마커 라이브러리 불러오기 */
                                                const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary("marker");

                                                /* 마커 설정하기 */
                                                const marker= new AdvancedMarkerElement({
                                                    map: map,
                                                    position: position,
                                                    title: "더 많은 정보가 필요하면 클릭하세요.." // 타이틀 설정
                                                });
                                            }

                                            initMap();
                                        
                                    

AdvancedMarkerElement 클래스는 기본 매개변수(map, position, title)를 제공하고, PinElement 클래스는 추가 맞춤설정을 위한 옵션을 제공한다

4. InfoWindow 클래스는 지도 위 지정된 위치(보통, 마커)의 팝업창에 컨텐츠를 표시해주는데, 이 팝업창은 컨텐츠 영역(content: 텍스트 문자열이나 DOM 노드)과 꼬리표(ariaLabel: 지정된 위치)로 구성된다:
[ 구글맵 정보창 작성 ]
                                        
                                            async function initMap() {
                                                ..

                                                /* 정보창 작성 */
                                                const contentString= "Kjc: 아직은.. 기다리세요. 삼릉 가는길, 등반 안내도, 갤러리 페이지(나중에 채웁니다 ㅡㅡ;)"
                                                const infowindow= new google.maps.InfoWindow({
                                                    content: contentString, ariaLabel: "삼릉마트" // 표시할 컨텐츠와 지정된 위치를 인수로 전달한다
                                                });

                                                /* 정보창 열기 이벤트 핸들러 */
                                                marker.addListener("click", () => {
                                                    infowindow.open({ anchor: marker, map }); // 앵커 포인트와 맵을 인수로 전달한다
                                                });
                                            }

                                            initMap();
                                        
                                    

정보창 작성 시; 이벤트 리스너도 함께 설정해주어야 한다!

5. 웹페이지에서 지도를 사용하려면 사용자가 확대/축소화면 이동 을 위해 지도와 상호작용하는 방식을 관리하는 특정 옵션이 필요할 수도 있다. 이러한 옵션은 MapOptions 인터페이스 내에서 정의하는데, gestureHandling: "greedy" 옵션을 주면; 구글 지도 위에서의 모든 터치 작업과 스크롤 이벤트에 반응한다:
                                    
                                        async function initMap() {
                                            ..

                                            map= new Map(document.getElementById("map"), { 
                                                center: position, zoom: zoom, mapId: "DEMO_MAP_ID",
                                                gestureHandling: "greedy" // 구글 지도 위에서의 모든 터치 작업과 스크롤 이벤트에 반응한다
                                            });
                                        }

                                        initMap();
                                    
                                

"cooperative" 옵션은(= 기본값임) 구글 지도 위에서 스크롤링 시 확대/축소되지 않고 정상적으로 페이지를 스크롤한다. 예컨대, 지도 위에서 스크롤을 시도하면; "지도를 확대/축소하려면 Ctrl 키를 누른 채 스크롤하세요"라는 메시지가 나타난다. 또한 터치 스크린 기기에서 지도를 두 손가락으로 움직여 확대/축소하고 화면 이동할 수도 있다

                                    
                                        map= new Map(document.getElementById("map"), { 
                                            center: position, zoom: zoom, mapId: "DEMO_MAP_ID",
                                            gestureHandling: "none", zoomControl: false // 모든 화면 이동 및 확대/축소 동작을 중지한다
                                        });
                                    
                                

gestureHandling: "none" 옵션은 zoomControl: false 옵션과 함께 사용해야 한다!


✓   화면 이동과 확대/축소 컨트롤을 허용하되, 지도를 특정 경계 또는 최소 및 최대 확대/축소로 제한하는 것이 바람직할 수도 있는데, restriction, minZoommaxZoom 옵션을 설정해주면 된다:

                                    
                                        map= new Map(document.getElementById("map"), { 
                                            center: position, zoom: zoom, mapId: "DEMO_MAP_ID",

                                            minZoom: zoom - 3, maxZoom: zoom + 3, // 줌 축소, 확대의 제한값 설정
                                            restriction: {
                                                latLngBounds: {
                                                    north: -10, south: -40, east: 160, west: 100, // 각 방향별 경계치 설정
                                                }
                                            }
                                        });
                                    
                                

맵작성 고급

벡터 지도 렌더링하기
Maps JavaScript API는 래스터와 벡터의 두 가지 지도를 제공한다: 래스터 지도는 기본적으로 로드되며, Google Maps Platform 서버측에서 생성된 후 웹 앱에 제공되는 픽셀 기반 래스터 이미지로 지도를 로드한다. 반면, 벡터 지도는 로드 시 WebGL을 사용하여 클라이언트 측에서 그려진다
[ 벡터 지도 설정하기 ]
                                        
                                            async function initMap() {
                                                let map

                                                const position= { lat: 35.79809, lng: 129.20654 }
                                                const zoom= 15

                                                /* RenderingType 라이브러리 로드 */
                                                const { Map, RenderingType } = await google.maps.importLibrary("maps");

                                                /* 맵 객체의 인스턴스 생성하기 */
                                                map= new Map(document.getElementById("map"), { 
                                                    center: position, zoom: zoom, mapId: "DEMO_MAP_ID",
                                                    renderingType: RenderingType.VECTOR // 벡터 지도로 설정한다
                                                });
                                            }
                                    
                                            initMap()
                                        
                                    

벡터 지도는 래스터 지도에 비해 시각적 충실도가 개선되고 지도에서 기울기와 방향을 제어할 수 있으므로 최상의 사용자 환경을 위해 권장된다!


✓   클라우드 기반 새 지도 ID를 만들려면; [Google Maps Platform] 자신의 계정에서 지도 관리 -> 지도 ID 만들기로 가서 새 지도 ID 를 만들어 지도 유형을 JavaScript 로 설정하고, 벡터 옵션을 선택해준다. 나아가, 지도에서 기울기 및 회전을 사용 설정하려면 기울기 및 회전 옵션도 선택해주면 된다 이제, 이러한 값을 프로그래매틱 방식으로 조정할 수 있으며 사용자가 지도에서 직접 기울기 및 회전 을 조정할 수도 있게된다!


Maps JavaScript APIMapType 객체를 사용하여 지도 유형 정보를 저장한다. Map에서 사용 중인 지도 유형은 동적으로 setMapTypeId("지도유형") 메서드를 호출하여 변경해줄 수 있다:

                                    
                                        /* 동적으로 지도유형 변경하기 */
                                        map.setMapTypeId("terrain");
                                    
                                

기본값인 roadmap 은 기본 도로지도 뷰로 표시하는데, satellite (위성지도 뷰), hybrid (일반 뷰와 위성 뷰를 혼합하여 표시한다), terrain (지형 정보를 기반으로 실제 지도를 표시한다)

마커 맞춤 설정
마커는 테두리(border), 배경(background), 글리프(glyph) 세가지 요소로 구성되는데, 원하는 모양 및 동작을 설정하려면; PinElement 클래스를 사용하면 된다:

[ 고급 마커 설정하기 ]
                                        
                                            /* 마커 라이브러리 불러오기 */
                                            const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary("marker");

                                            const pin= new PinElement({ scale: 1.5 }); // 핀 크기 설정
                                            const pinBackground= new PinElement({ background: '#FBBC04' }); // 핀 배경색
                                            const pinBorder= new PinElement({ borderColor: '#137333' }); // 핀 테두리색
                                            const pinGlyph= new PinElement({ glyphColor: 'white' }); // 글리프 색상

                                            /* 고급 마커 설정하기 */
                                            const marker= new AdvancedMarkerElement({
                                                map: map, position: position, title: "더 많은 정보가 필요하면 클릭하세요..",
                                                content: pin.element, // 글리프 설정하기
                                                content: pinBackground.element,
                                                content: pinBorder.element,
                                                content: pinGlyph.element,
                                            });
                                        
                                    

글리프를 숨길 때는 빈 문자열을 전달해주면 된다: new PinElement({ glyph: '' });


✓   글리프에 텍스트를 넣을 때는 아래와 같이 색상도 함께 설정해주어야 한다: PinElement.glyph & glyphColor

                                    
                                        const pinText= new PinElement({ glyph: '3', glyphColor: 'white' }); // 글리프에 텍스트 및 색상 넣기

                                        const marker= new AdvancedMarkerElement({
                                            map: map, position: position, title: "더 많은 정보가 필요하면 클릭하세요..",
                                            content: pinText.element // 글리프 대신 텍스트 넣기
                                        });
                                    
                                

맞춤마커 종합 예)

간단한 html 마커
AdvancedMarkerElement는 DOM 요소이므로 Css 스타일을 마커에 직접 적용하고, html 및 Css를 사용하여 맞춤 마커를 처음부터 완전히 새로 만들 수 있다: 모든 AdvancedMarkerElement 인스턴스는 html 요소로 DOM에 추가되며, html 요소는 element 속성을 통해 액세스하고 다른 DOM 요소와 동일한 방식으로 조작할 수 있다

html 마커 예)

선/도형 그리기

선 그리기
Polyline 클래스는 지도에서 연결된 선분의 선형 오버레이를 정의하는데, 일련의 { Lat, Lng } 위치로 구성되어 순서대로 연결하는 일련의 직선 선분을 그려준다:
                                    
                                        async function initMap() {
                                            ..

                                            // 선 배열 정의
                                            const pathlines= [
                                                { lat: 35.824978, lng: 129.224602 }, // 상서장(&주차공간)
                                                { lat: 35.822087, lng: 129.219304 }, // 도당터널(&식물원) -> 올렛길 등산로
                                                { lat: 35.819609, lng: 129.218770 }, // 김호장군 고택 -> 올렛길 등산로 
                                                { lat: 35.815968, lng: 129.212632 }, // 나정
                                                { lat: 35.815836, lng: 129.218495 }, // 남간사지 석정 -> 일성왕릉 -> 해목령
                                                { lat: 35.813786, lng: 129.217043 }, // 남간사지 당간지주 -> 해목령 등산로 
                                                { lat: 35.810557, lng: 129.216017 }, // 창림사지 삼층석탑
                                                { lat: 35.807016, lng: 129.213040 }, // 포석정지(방문자센터 & 포석정주차장) -> 남산순환도로 
                                                { lat: 35.804390, lng: 129.211435 }, // 지마왕릉(태진지 저수지) -> 삼층석탑
                                                { lat: 35.801901, lng: 129.211222 }, // 삼불사 석조여래삼존입상(주차공간 & 버스) -> 등산로
                                                { lat: 35.796113, lng: 129.208842 }, // 삼릉 & 경애왕릉(버스) -> 등산로
                                            ];

                                            const flightPath= new google.maps.Polyline({ // 연결된 직선 생성하기
                                                path: pathlines, // 선 배열을 가져온다
                                                geodesic: true, // 선이 지구의 곡선을 따르도록 한다
                                                strokeColor: "#FF0000", // 선 색상 ← 16진수 html 색상
                                                strokeOpacity: 1, // 선의 불투명도 ← 0.0 ~ 1.0
                                                strokeWeight: 3, // 선의 두께 ← 픽셀
                                                editable: true // 사용자가 드래그할 수 있도록 한다
                                            });

                                            flightPath.setMap(map)

                                            ..
                                        }

                                        initMap();
                                    
                                

geodesic: 값이 true 인 경우; 다각형의 가장자리가 지구의 곡선을 따르며, false 인 경우; 다각형의 가장자리가 화면 공간에서 직선으로 렌더링된다

선 그리기 예)

도형 작성하기
Symbol은 Marker 또는 Polyline 객체에 표시할 수 있는 벡터 기반 아이콘으로서, 기호의 모양은 SVG 경로 표기법을 사용한 경로로 정의된다. Symbol 객체는 획과 채우기의 색상 및 두께와 같은 시각적 측면을 맞춤설정할 수 있는 다양한 속성을 지원한다
1. Maps JavaScript APISymbolPath 클래스를 통해 마커나 선에 추가할 수 있는 기본 기호를 제공하는데, 다중선에 기호를 표시하려면 PolylineOptions 객체의 icons[] 배열로 된 하나 이상의 IconSequence 객체 리터럴 값을 설정해주어야 한다:
                                    
                                        async function initMap() {
                                            ..

                                            // Google Maps JavaScript API에서 제공하는 미리 정의된 화살표 기호 사용
                                            const lineSymbol= {
                                                path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW
                                                // path: google.maps.SymbolPath.BACKWARD_CLOSED_ARROW ← 닫힌, 뒤쪽/앞쪽을 가리키는 화살표
                                                // path: google.maps.SymbolPath.BACKWARD_OPEN_ARROW ← 열린, 뒤쪽을 가리키는 화살표
                                                // path: google.maps.SymbolPath.FORWARD_OPEN_ARROW ← 열린, 앞쪽을 가리키는 화살표
                                                // path: google.maps.SymbolPath.CIRCLE ← 원
                                            };

                                            // 폴리선을 만들고 'icons' 속성을 통해 기호를 추가한다
                                            const line= new google.maps.Polyline({
                                                path: [
                                                    { lat: 35.771988, lng: 129.235597 }, // 선의 시작 지점
                                                    // .. 선의 중간 지점들
                                                    { lat: 35.77122, lng: 129.2301 }, // 선의 끝 지점
                                                    // 선의 시작, 끝 지점
                                                ],

                                                icons: [
                                                    {
                                                        icon: lineSymbol, // 선에 렌더링할 기호
                                                        offset: "100%" // 선의 시작 부분으로부터 아이콘이 렌더링될 거리 ← 기본값: 100%
                                                        repeat: 0 // 선 위의 연속적인 아이콘 사이의 거리 ← 기본값: 0
                                                    },
                                                    // ..
                                                ],

                                                map: map
                                            });

                                            ..
                                        }

                                        initMap();
                                    
                                

도형 그리기 예)

2. 다중선의 불투명도를 0 으로 설정하고 선 위에 일정한 간격으로 불투명한 기호를 오버레이하여 점선 효과를 나타낼 수 있다:
                                    
                                        async function initMap() {
                                            ..

                                            const lineSymbol= {
                                                path: 'M 0,-1 0,1', strokeOpacity: 1, scale: 4 // SVG 경로 표기법을 사용하여 불투명도가 1인 기호를 정의한다
                                            };

                                            // 폴리선을 만들고 'icons' 속성을 통해 기호를 추가한다
                                            const line= new google.maps.Polyline({
                                                path: [
                                                    { lat: 22.291, lng: 153.027 }, { lat: 18.291, lng: 153.027 },
                                                ],

                                                strokeOpacity: 0, // 선의 불투명도를 0으로 지정하고, 
                                                icons: [
                                                    {
                                                        icon: lineSymbol,
                                                        offset: '0', repeat: '20px' // 20픽셀 간격으로 기호를 반복하여 파선 효과를 만든다
                                                    },
                                                ],

                                                map: map
                                            });

                                            ..
                                        }

                                        initMap();
                                    
                                

좀, 많이,, 복잡합니다만.. SVG 경로 표기법에 관해서 필요하시면; Path data 를 참조하시기 바랍니다 ㅡㅡ;

3. DOM의 window.setInterval() 함수를 써서 일정한 간격으로 기호의 오프셋을 변경하여 경로를 따라 기호를 애니메이션으로 표시해줄 수 있다:
                                    
                                        async function initMap() {
                                            ..

                                            const lineSymbol= {
                                                path: google.maps.SymbolPath.CIRCLE,
                                                scale: 8, strokeColor: "#393",
                                            };

                                            // 폴리선을 만들고 'icons' 속성을 통해 기호를 추가한다
                                            const line= new google.maps.Polyline({
                                                path: [
                                                    { lat: 22.291, lng: 153.027 }, { lat: 18.291, lng: 153.027 },
                                                ],

                                                icons: [
                                                    {
                                                        icon: lineSymbol,
                                                        offset: "100%" // 선의 시작 부분으로부터 아이콘이 렌더링될 거리 ← 기본값: 100%
                                                    },
                                                ],

                                                map: map
                                            });
                                            
                                            animateCircle(line);
                                            ..
                                        }

                                        // DOM setInterval() 함수를 사용하여 고정된 간격으로 기호의 오프셋을 변경한다
                                        function animateCircle(line) {
                                            let count= 0;

                                            window.setInterval(() => {
                                                count= (count + 1) % 200;
                                                const icons= line.get("icons")

                                                icons[0].offset= count / 2 + "%";
                                                line.set("icons", icons)
                                            }, 100);
                                        }

                                        initMap();
                                    
                                

4. 마커에 기호 추가하기:
                                    
                                        async function initMap() {
                                            ..

                                            const lineSymbol= {
                                                path: google.maps.SymbolPath.CIRCLE,
                                                scale: 8, strokeColor: "#393",
                                            };

                                            // 폴리선을 만들고 'icons' 속성을 통해 기호를 추가한다
                                            const line= new google.maps.Polyline({
                                                path: [
                                                    { lat: 22.291, lng: 153.027 }, { lat: 18.291, lng: 153.027 },
                                                ],

                                                icons: [
                                                    {
                                                        icon: lineSymbol,
                                                        offset: "100%" // 선의 시작 부분으로부터 아이콘이 렌더링될 거리 ← 기본값: 100%
                                                    },
                                                ],

                                                map: map
                                            });
                                            
                                            animateCircle(line);
                                            ..
                                        }

                                        // DOM setInterval() 함수를 사용하여 고정된 간격으로 기호의 오프셋을 변경한다
                                        function animateCircle(line) {
                                            let count= 0;

                                            window.setInterval(() => {
                                                count= (count + 1) % 200;
                                                const icons= line.get("icons")

                                                icons[0].offset= count / 2 + "%";
                                                line.set("icons", icons)
                                            }, 100);
                                        }

                                        initMap();
                                    
                                

맵 작성 나머지..

마커 접근성
클릭 이벤트 처리를 사용 설정하고, 스크린 리더용 설명 텍스트를 추가하고, 마커 크기를 조정하여 마커의 접근성을 높일 수 있다

클릭가능한 마커 예)

마커 클러스터링
Markerclusterer 라이브러리를 Maps JavaScript API와 함께 사용하면 가까이 있는 마커를 클러스터로 결합하고 지도상에 마커를 간단하게 표시할 수 있다:

마커클러스터링 예)

기기 위치정보
브라우저의 위치정보 기능을 Maps JavaScript API와 함께 사용하여 Google 지도에 기기의 지리적 위치를 표시할 수 있다. 이 지리적 위치는 사용자가 위치 공유를 허용한 경우에만 표시되며, W3C navigator.geolocation API를 통해 기기의 위치를 결정한다

기기 위치정보 예)

맵지도 데이터 시각화
deck.gl은 2D 및 3D 데이터 시각화를 제공하고 대용량 데이터 세트를 지원하는 WebGL 기반 시각화 프레임워크로서, GoogleMapsOverlay 클래스를 사용하여 Maps JavaScript API에 deck.gl 데이터 시각화를 추가할 수 있다
구글맵 Place
Place 클래스를 사용하면 앱에서 위치 인식 기능을 만들고, 필요에 따라 맞춤 설정할 수 있는 지능형 검색기능을 통해 사용자에게 자세한 위치 데이터를 제공할 수 있다
wave