본문 바로가기

React

[React] Kakao map api 2

지난 포스트에서 단순히 지도를 띄우는 것까지 해보았다.

 

이번에는 지난 프로젝트에서 사용했던 몇가지 옵션들에 대해서 포스트하려한다.

 

map api를 사용하면서 대표적으로 추가하는 건 아무래도 오버레이와 마커일 것이다.

커스텀 훅으로 만든 만큼 오버레이와 마커 역시 여기에 맞추어서 수정해주어야한다.

 

...
	setMapDetails({
		option: options
	});
...
return mapDetails;

 

커스텀 훅의 마지막 부분이다.

커스텀 훅의 반환 값이 mapDetails인데 이 부분이 무엇인지를 들여다보면 내부에 객체가 존재한다는 것을 알 수 있다.

이 객체가 생성하고자 하는 맵의 옵션들인 것이다.

 

그러니까 마커와 오버레이를 생성하는 기본형도 맵에 옵션으로 추가하는 방식이기 때문에,

저기에 보이는 setMapDetails에 오버레이와 마커의 옵션을 삽입해주면 된다.

...
	setMapDetails({
    		option: options,
        	markers: markers,
        	overlays: overlays,
	});
...

 

이제 그럼 markers와 overlays에 값을 구체화한다.

 

마커는 간단하다. 마커를 표시할 위치만 있으면 된다.

const markers = new kakao.maps.Marker({ position: markerPosition });
//여기서 markerPosition은 마커의 위치 좌표이다.
//객체에 clickable: true와 같은 마커의 옵션도 추가 가능하다.

 

만약 여러 개의 마커를 표시하고 싶다면 좌표 객체를 여러개 가진 배열로 만들어주면 된다.

const markers = markerPositions.map(markerPosition => new kakao.maps.Marker({ 
	position: markerPosition 
}));

 

다음으로는 오버레이이다.

오버레이에는 다양한 정보가 포함될 수 있다.

쉽게 말하면 그냥 지도 위에 표기되는 일반적인 DOM요소이다.

그러니까 div, img 등의 태그가 올 수 있기에 원하는 요소를 직접 만들어주어야 한다.

 

//contents : 오버레이에 표기해줄 컨텐츠 내용 객체 배열
//주로 마커 위에 해당 위치의 인포를 띄워주기 위한 용도 이기에 markerPositions를 재활용하겠다.
const overlays = markerPositions.map((markerPos, index) => {
    const imgSrc = content[index].img_src;			//오버레이에 보여줄 이미지
    const infoText = content[index].contentText;	//오버레이에 보여줄 텍스트
    
    //여러 가지의 컨텐츠가 존재하니, 먼저 컨텐츠들을 담을 컨테이너를 만들어준다.
    const contentDiv = document.createElement('div');
    //컨테이너의 구분을 위해 className을 지정해준다.
    contentDiv.className = 'customoverlay';
    
    //이미지 요소 생성
    const imgElement = document.createElement('img');
    imgElement.src = imgSrc;	//이미지 경로 설정
    
    //컨테이너에 이미지(img) 요소 삽입
    contentDiv.appendChild(imgElement);
    
    //텍스트 요소 생성
    const textElement = document.createElement('div');
    textBox.className = 'text_box';
    textBox.innerHTML = infoText;	//텍스트 내용 설정
    
    //컨테이너에 텍스트(div) 요소 삽입
    contentDiv.appendChild(textElement);
    
    //배열에 반환할 객체
    const overlay = new kakao.maps.CustomOverlay({
    	content: contentDiv,
        position: markerPos,
        //마커와 겹치지 않도록 위치 조절
        xAnchor: -0.1,
        yAnchor: 0.5,
    });
    
    return overlay;
});

 

이렇게 요소를 생성하고 내용을 담아 위치와 함께 반환해주면된다.

 

최종 전체 코드이다.

useEffect(() => {
    if(markerPositions.length > 0) {
    	const options = {
    		center: positions,
        	level: 3,
    	};
        
    	const markers = markerPositions.map(markerPosition => new kakao.maps.Marker({ 
		    position: markerPosition 
		}));
        
		const overlays = markerPositions.map((markerPos, index) => {
    		const imgSrc = content[index].img_src;			//오버레이에 보여줄 이미지
    		const infoText = content[index].contentText;	//오버레이에 보여줄 텍스트
    
    		//여러 가지의 컨텐츠가 존재하니, 먼저 컨텐츠들을 담을 컨테이너를 만들어준다.
    		const contentDiv = document.createElement('div');
    		//컨테이너의 구분을 위해 className을 지정해준다.
    		contentDiv.className = 'customoverlay';
    
    		//이미지 요소 생성
    		const imgElement = document.createElement('img');
    		imgElement.src = imgSrc;	//이미지 경로 설정
    
    		//컨테이너에 이미지(img) 요소 삽입
    		contentDiv.appendChild(imgElement);
    
    		//텍스트 요소 생성
    		const textElement = document.createElement('div');
    		textBox.className = 'text_box';
    		textBox.innerHTML = infoText;	//텍스트 내용 설정
    
    		//컨테이너에 텍스트(div) 요소 삽입
    		contentDiv.appendChild(textElement);
    		
    		//배열에 반환할 객체
    		const overlay = new kakao.maps.CustomOverlay({
    		    content: contentDiv,
    		    position: markerPos,
    		    //마커와 겹치지 않도록 위치 조절
    		    xAnchor: -0.1,
    		    yAnchor: 0.5,
    		});
    		
    		return overlay;
	    });
        
		setMapDetails({
    			option: options,
    			markers: markers,
    			overlays: overlays,
		});
    }
}, [positions, markerPositions, contents]);

 

이렇게 마커와 오버레이를 포함한 mapDetails를 반환해주면 된다.

 

물론, 여기까지는 모두 맵 옵션이기 때문에, 사용하고자 하는 컴포넌트나 페이지에서 DOM요소를 생성해 전달해주어야한다.

 

import { useRef } from "react";
...

const MapComp = () => {
    const mapContainerRef = useRef(null);
    const mapRef = useRef(null);
    ...
    
    useEffect(() => {
        if (mapContainerRef.current && option.center && markers.length > 0) {
            const map = new kakao.maps.Map(mapContainerRef.current, option);
            mapRef.current = map;
            markers.forEach(marker => marker.setMap(map));
            overlays.forEach(overlay => overlay.setMap(null));
        }
    }, [option, markers]);
    
    ...

 

이렇게 new kakao.maps.Map();을 통해 지도를 생성해주고, 내부에 mapContainerRef.current로 DOM요소를 지정해준다.

또한, 이렇게 생성된 맵을 map의 초기화 값으로 지정해 이후에 marker와 overlay를 초기화하는데 이용한다.

 

 

 

'React' 카테고리의 다른 글

[React] filter의 무한루프와 useMemo  (0) 2024.11.14
[React] useRef  (0) 2024.11.13
[React] Kakao map api 1  (1) 2024.11.08
[React] useEffect의 무한루프 에러  (1) 2024.07.24
[React] useMemo  (0) 2024.07.24