1편 글은 여기로!
https://kkt102.tistory.com/119
[React] 카카오맵 API 커스텀 해보기-1
따로 사이드 프로젝트와 회사 프로젝트를 진행하다보니 생각보다 카카오맵을 많이 사용하게되서 혹시라도 저와 비슷한 고민을 하는분들이 있지 않을까 싶어 작성하게 됬습니다. 절대로 100% 정
kkt102.tistory.com
저번 1편에 지도출력, 현재위치 랜더링, 마커, 마커변경에서 이어지는 글 입니다.
1. 마커는 표시됬고 현재위치 마커에서 특정 반경을 표시해주고싶은데...?
이번에는 마커 중심으로 도형을 그려보겠습니다!
저는 해당 기능을 마커 중심에서 특정 반경을 표시할 때 사용해봤습니다. 사실 얼마나 정확한지는 모르겠지만...
가장 기본적인 원형을 띄우는 코드입니다.
const KakaoMap = () => {
const kakaoMaps = useRef(null);
const [map, setMap] = useState(null);
const getKakao = () => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
const mapContainer = document.getElementById("map");
if (!map) {
const mapOptions = {
center: new window.kakao.maps.LatLng(
position.coords.latitude,
position.coords.longitude
),
level: 4,
};
const map = new window.kakao.maps.Map(mapContainer, mapOptions);
// MY POSITION MARKER
const myPosition = new window.kakao.maps.LatLng(
position.coords.latitude,
position.coords.longitude
);
const myMarker = MyMarkerIcon,
myMarkerSize = new window.kakao.maps.Size(20, 20),
myMarkerOption = { offset: new window.kakao.maps.Point(0, 0) };
const myMarkerPosition = new window.kakao.maps.MarkerImage(
myMarker,
myMarkerSize,
myMarkerOption
);
const marker = new window.kakao.maps.Marker({
map: map,
image: myMarkerPosition,
position: myPosition,
});
// USER RANGE CIRCLE
const circle = new window.kakao.maps.Circle({
center: new window.kakao.maps.LatLng(
position.coords.latitude,
position.coords.longitude
),
radius: 300,
strokeWeight: 2,
strokeColor: "#6556FF",
strokeOpacity: 0.2,
strokeStyle: "solid",
fillColor: "#6556FF",
fillOpacity: 0.05,
});
circle.setMap(map);
setMap(map);
}
});
} else {
console.log("내위치를 사용할 수 없어요.");
}
};
useEffect(() => {
getKakao();
}, []);
return (
<div
id="map"
ref={kakaoMaps}
style={{width: "100vw",height: "100vh}}
></div>
);
};
export default KakaoMap;
일단 해당 코드는 내 위치의 마커+반지름 300m 의 반지름을 표시하는 코드입니다.
먼저 도형을 그리는 코드를 살펴보겠습니다!
먼저 center의 경우 도형의 중심을 지정해주는 옵션입니다. 샘플 코드에서는 위에 geolocation으로 받아온 접속한 사용자의 중심좌표로 지정해뒀습니다.
radius 는 원의 반지름을 m 단위로 입력해줄 수 있는 옵션입니다.
strokeWeight 의 경우는 원의 외부에 보여지는 라인의 두깨를 지정하는 옵션!
즉 border-width 값을 px 단위로 입력해줍니다.
strokeColor 은 말그대로 stroke의 색상을 지정해주는 옵션입니다.
strokeOpacity 는 stroke의 투명도! 만약 해당 옵션을 아예 설정하지 않았다면 기본값인 1 로 설정됩니다.
strokeStyle 은 말그대로 border-style을 설정하는 옵션입니다.
fillColor 은 원형 내부의 색상을 설정하는 옵션입니다.
fillOpacity 는 원형의 투명도를 설정해주는 옵션입니다.
현재는 도형을 원형밖에 사용해보지 않았습니다만 카카오맵 API 가이드를 확인해보면 원형만 있는게 아니라
선이나 사각형, 다각형까지 그려줄 수 있습니다.
각 그리는 도형마다 내부의 옵션값들이 조금씩 변경됩니다.
추후에 선, 사각형, 다각형을 다양한 방법으로 사용하는 방법을 포스팅하겠습니다!!!
2. 자 이번에는 여러개의 마커를 띄어주고 클러스터러도 적용하고 싶은데!!!
다음으로는 여러개의 마커를 띄운 후 클러스터러를 적용해보겠습니다.
단순하게 내 위치 중심의 좌표가 아닌 다양한 좌표에 마커를 띄우고 싶은 경우가 있습니다.
예를들어 키워드 검색을 통해 나온 결과들의 장소, 혹은 고정적으로 입력해놓은 좌표에 대한 마커와 같이
여러개의 마커를 띄우는 방법을 알아보겠습니다. 일단 채찍피티(?) 에 문의해본 결과
대한민국 한정 위도는 33.2491 ~ 37.8779 까지이며 경도는 126.9994 ~ 129.9993 이라고 답을 들었습니다!
위도나 경도값이 소수점 한자리만 바뀌어도 지도상에서는 위치가 많이 달라지기 때문에 확인이 필요합니다!
혹 원하는 지도상의 위도/경도값을 찾고싶은 경우는 아래의 사이트를 참고하시면 될 듯 합니다!!
위도경도찾기
위도경도찾기, IP 주소확인, 일출일몰 시간, 위도경도 정의
map.esran.com
지도로 위도 경도 좌표 찾기
지도에 직접 마우스를 클릭하여 위도 경도를 확인 할 수 있습니다. 또한 검색창에 주소나 위치를 입력하면 검색된 결과로 지도로 이동하여 표시 됩니다.
www.findlatlng.org
자 그럼 일단 코드를 먼저 보겠습니다
const KakaoMap: React.FC = () => {
const myKakaoMaps = useRef(null);
const dummyData = useRecoilValue(dummyDateState);
const [map, setMap] = useState(null);
const [userLat, setUserLat] = useState(0);
const [userLng, setUserLng] = useState(0);
const getKakao = () => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
setUserLat(position.coords.latitude);
setUserLng(position.coords.longitude);
let locPosition = new window.kakao.maps.LatLng(
position.coords.latitude,
position.coords.longitude
);
const mapContainer = document.getElementById("map");
if (!map) {
const mapOptions = {
center: new window.kakao.maps.LatLng(
position.coords.latitude,
position.coords.longitude
),
level: 5,
};
const map = new window.kakao.maps.Map(mapContainer, mapOptions);
const clusterer = new window.kakao.maps.MarkerClusterer({
map: map,
averageCenter: true,
minLevel: 5,
calculator: [99, 999, 9999],
disableClickZoom: true,
styles: [
{
display: "flex",
alignItems: "center",
justifyContent: "center",
width: "40px",
height: "50px",
paddingBottom: "22%",
background: `url(${MapMarkerIcon}) no-repeat center center`,
backgroundSize: "40px 50px",
fontSize: "18px",
fontWeight: 700,
color: `let(--point-color)`,
},
{
display: "flex",
alignItems: "center",
justifyContent: "center",
width: "50px",
height: "60px",
paddingBottom: "26%",
background: `url(${MapMarkerIcon}) no-repeat center center`,
backgroundSize: "50px 60px",
fontSize: "18px",
fontWeight: 700,
color: `let(--point-color)`,
},
{
display: "flex",
alignItems: "center",
justifyContent: "center",
width: "70px",
height: "80px",
paddingBottom: "26%",
background: `url(${MapMarkerIcon}) no-repeat center center`,
backgroundSize: "70px 80px",
fontSize: "18px",
fontWeight: 700,
color: `let(--point-color)`,
},
],
});
const individualMarkers: any = [];
dummyData?.forEach((position) => {
const MarkerSrc = MapMarkerIcon;
const MarkerSize = new window.kakao.maps.Size(45, 55);
const MarkerInfo = new window.kakao.maps.MarkerImage(
MarkerSrc,
MarkerSize
);
const marker = new window.kakao.maps.Marker({
position: new window.kakao.maps.LatLng(
position.location_lat,
position.location_lon
),
image: MarkerInfo,
});
individualMarkers.push(marker);
});
clusterer.addMarkers(individualMarkers);
map.setMinLevel(2);
map.setMaxLevel(5);
map.setDraggable(false);
setMap(map);
}
});
} else {
console.log("내위치 사용 불가");
}
};
useLayoutEffect(() => {
getKakao();
}, []);
return (
<div
id="map"
ref={myKakaoMaps}
style={{width: `100vw`, height: `100vh`}}
></div>
);
};
export default KakaoMap;
일단 저는 dummyData라는 state 에 여러개의 마커를 띄우기 위한 정보를 저장시켜놨습니다.
사실은 마커를 생성할 때 필요한 위도, 경도 값만 있어도 되지만 제가 작업 할 떄 필요한 해당 가게의 주소와 명칭 등을 추가로 넣어준 상태입니다.
먼저 클러스터러를 설정해 주겠습니다!
기본적인 클러스터러 예제 또한 카카오맵 API 문서에 잘 나와있으니 참고하시면 좋을 것 같습니다!
https://apis.map.kakao.com/web/sample/basicClusterer/
averageCenter 값은 boolean으로 되어있는데 일단 전 가이드에 맞춰서 true 로 설정해놨습니다.
공식문서에서는 해당 클러스터에 포함 된 마커들의 평균값을 클러스터 위치로 표시한다고 하는데 아마 false 로 설정하면 클러스터들의 위치를 임의로 설정해줄 수 있는 것 같습니다.
다음으로 minLevel 의 경우는 클러스터가 작동 될 최소한의 지도 크기를 설정해주면 됩니다. 전 5로 설정해놨기 때문에 지도 확대레벨이 4일 경우는 자동으로 클러스터가 적용되지 않고 모든 마커들이 각 좌표의 값에 보여지게 됩니다.
disableClickZoom 의 옵션은 클러스터를 클릭했을 때 지도가 확대될지를 설정해주는 값 입니다. 해당 값을 false 로 설정 할 경우 클러스터를 클릭/터치해도 지도가 확대되지 않습니다.
다음으로 calculator 의 값은 클러스터의 크기 구분 값 입니다. 해당 값들을 기준으로 스타일일나 문자를 지정해줄 수 있습니다. 제가 지정한 값에서는 1~99, 100~999, 1000~9999 의 클러스터러를 각각 다른 스타일, 텍스트로 표현할 수 있게됩니다. 저는 스타일만 따로 지정하였습니다.
그다음 스타일인데 스타이를 리터럴 작성법으로 표기해주며 각 스타일은 calculator 에 선언해준 값과 순서를 기준으로 적용됩니다. 즉 1번째 스타일은 1~99 에만 적용되고 2번째 스타일은 100~999... 이런식으로 적용됩니다.
그리고 마지막으로 clusterer.addMarkers(individualMarkers); 를 통해 클러스터러에 마커들을 추가 해줍니다.
해당 옵션에 대한 기본적인 설명은 아래의 카카오맵 API 가이드 문서를 참고하시면 좋을 것 같습니다!
https://apis.map.kakao.com/web/sample/chickenClusterer/
일단 individualMarkers 라는 빈 배열을 만들어 줍니다. 그 다음 forEach문을 사용하여 dummyData라는 state를 풀어줍니다!
코드를 보시면 마커를 띄우기 위해 위도, 경도값만 사용되고 있습니다. 그 이외의 옵션은 기본적인 마커를 띄우는 방법과 동일합니다. 커스텀 마커를 띄울 떄 사용되는 이미지의 크기 및 이미지 주소 입니다.
그리고 individualMarkers 에 밀어넣어줍니다.
해당 코드가 실행 되면 아래와 같이 지도 레벨에 따라 클러스터와 마커가 표시됩니다.
3. 마커 클릭했을 때 뭔가 다른 이벤트를 걸어주는건???!
마커에 이벤트를 거는 방법은 조금 간단(?)합니다.
dummyData?.forEach((position) => {
const MarkerSrc = MapMarkerIcon;
const MarkerSize = new window.kakao.maps.Size(45, 55);
const MarkerInfo = new window.kakao.maps.MarkerImage(
MarkerSrc,
MarkerSize
);
const marker = new window.kakao.maps.Marker({
position: new window.kakao.maps.LatLng(
position.location_lat,
position.location_lon
),
image: MarkerInfo,
});
// 추가되는 부분
window.kakao.maps.event.addListener(marker, "click", function () {
console.log(marker);
});
// 추가되는 부분
individualMarkers.push(marker);
});
위와같은 코드처럼 forEach 부분에서 이벤트를 추가해주면 각 마커에 대하여 개별 이벤트를 적용시킬 수 있습니다!
마커 클릭 이벤트에 관한 정보 또한 카카오맵 API 가이드문서에 잘 나와있으므로 참고하시면 좋을 것 같습니다!
https://apis.map.kakao.com/web/documentation/#Marker_click
위의 이벤트를 통해 marker 정보를 찍어보면 아래와 같은 정보가 나옵니다!
다만 저 값들이 정확하게 어떤 것을 뜻하고 어떤 정보를 담고 있는지는 정확하게 파악하지는 못했습니다.
제게 필요한 정보가 아니다보니 그냥 넘어가기도 해서 그렇습니다..
아시는분은 댓글 달아주시면 감사하겠습니다!
일단 카카오맵 커스텀은 이정도까지만 하겠습니다.
저도 사실 혼자했다고하면 거짓말이고 채찍피티(?) 의 도움을 많이 받아서 진행했고 조금 더 수정을 거쳐 제가 원하는 동작을 하는 지도로 커스텀을 완료하였습니다!
이 글을 통해 조금이라도 도움이 되시면 좋겠습니다....!
지금까지 설명을 더 못하는 글 읽어주셔서 감사하고 언제나 잘못된 부분을 지적하는 댓글은 감사합니다!
'Programming > React' 카테고리의 다른 글
[React] 카카오맵 API 커스텀 해보기-1 (1) | 2024.03.30 |
---|---|
[React] TypeScript에서 Swiper 사용하기 (0) | 2024.01.13 |
[React] axios POST API 이미지와 함께 보내기 (1) | 2023.09.20 |
[React]map 함수로 만든 메뉴에 개별 이벤트 걸기 (0) | 2023.03.03 |
[React] map 함수안에 array 배열 뿌리기 (0) | 2022.10.20 |