지난 포스트에서 단순히 지도를 띄우는 것까지 해보았다.
이번에는 지난 프로젝트에서 사용했던 몇가지 옵션들에 대해서 포스트하려한다.
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 |