리액+카맵 삼회차 . .
이번엔 타입스크립트 빠샤
타입스크립트로 프로젝트를 연다면, 아래와 같이 실행한다.
npx create-react-app --template typescript
자바스크립트로 이미 진행중인 프로젝트에 타입스크립트를 도입하겠다면,
npm install --save typescript @types/node @types/react @types/react-dom
타입스크립트 모듈만 설치해주고
App.js -> App.tsx
index.js -> index.ts 로 변경해준다.
'내 어플리케이션 '에서 앱키를 얻을 수있다.
이 중 JavaScript 키
를 이용한다.
index.html 중 <head >안에
<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey={JavaScript 키}&libraries=services"></script>
.env에서 관리하려면 ??
.env파일을 만들고
REACT_APP_변수명 = 키값 (ex. REACT_APP_JS_KEY=123456789)
script src에서 변수 포맷팅
" ... appkey=%REACT_APP_KEY% "
변수를 %안에 둔다.
💥 env 설정후에는 꼭 노드를 다시 시작해야 한다. npm start
내 애플리케이션>앱 설정>플랫폼에 작업하는 페이지 주소를 등록한다.
(localhost주소 등)
declare global {
interface Window {
kakao: any;
}
}
import React from 'react';
import MapContainer from './map/MapContainer';
function App() {
return (
<div className="App">
<MapContainer />
</div>
);
}
export default App;
import React, { useEffect } from 'react';
declare global {
interface Window {
kakao: any;
}
}
const MapContainer = () => {
useEffect(() => {
let container = document.getElementById('map'); //지도를 담을 영역의 DOM 레퍼런스
let options = { //지도를 생성할 때 필요한 기본 옵션
center: new window.kakao.maps.LatLng(33.450701, 126.570667), //지도의 중심좌표.
level: 3 //지도의 레벨(확대, 축소 정도)
};
let map = new window.kakao.maps.Map(container, options); //지도 생성 및 객체 리턴
}, [])
return (
<div id="map" style={{ width: "100vw", height: "100vh" }} />
);
}
export default MapContainer;
https://apis.map.kakao.com/web/sample/basicInfoWindow/
하나의 인포윈도우만 생성한다면 위의 문서대로 적용하면 된다.
아래는 실제 프로젝트에서 이용할때 데이터를 불러와서 적용하는 경우이다.
프론트단에서만 개발인 상황, 데이터는 dummy.data에서 불러온다.
const MapContainer = () => {
useEffect(() => {
let container = document.getElementById('map'); //지도를 담을 영역의 DOM 레퍼런스
let options = { //지도를 생성할 때 필요한 기본 옵션
center: new window.kakao.maps.LatLng(37.586272, 127.029005), //지도의 중심좌표
level: 1 //지도의 레벨(확대, 축소 정도)
};
let map = new window.kakao.maps.Map(container, options); //지도 생성 및 객체 리턴
//---> 기본 맵 container, options, map 설정.
for (let i=0; i< dummy.data.length; i++){
displayMarker(dummy.data[i],i);
}
function displayMarker<T extends {name: string, location_y: number, location_x: number, active: boolean, point:number}>(data: T, i: number) {
// 인포윈도우 표시될 위치(좌표)
let iwPosition = new window.kakao.maps.LatLng(data.location_y, data.location_x);
// 인포윈도우에 표출될 내용. HTML 문자열이나 document element 등이 가능하다.
var inactiveInfoWindow = `<div class="inactive infowindow""><span>${data.name}</span></div>`;
//인포윈도우
let infowindow;
infowindow = new window.kakao.maps.InfoWindow({
zIndex: 1,
position: iwPosition,
content: inactiveInfoWindow,
disableAutoPan: false,
map: map //map에 해당 인포윈도우를 적용한다.
});
}
//중심좌표 재설정
var position = new window.kakao.maps.LatLng(37.586272, 127.029005);
map.setCenter(position);
}
});
}, [])
인포윈도우 크기, 디자인, 이벤트 커스터마이징 하기
위의 인포윈도우 생성 코드 중
// 인포윈도우에 표출될 내용. HTML 문자열이나 document element 등이 가능하다.
var inactiveInfoWindow = `<div class="inactive infowindow""><span>${data.name}</span></div>`;
여기서 설정한 것이 인포윈도우에 쓰여질 내용이다.
개발자도구 창에 클릭되어있는 파란부분의 div안에 들어간다.
우리가 코드에서 선언하고 디자인한 내용은 그 안에 들어갈 뿐이다.
하지만, 인포윈도우의 크기, 색깔, 디자인 등은 파란부분div 혹은 그의 부모, 형제 요소들로 조정해얗나다.
다음과 같이 커스터마이징 할 수 있다.
var infoTitle = document.querySelectorAll('.infowindow');
// 코드에 적용한 '인포윈도우에 표출될 내용'을 담은 태그에 적용한 class명(혹은id명)을 선택자를 이용하여 불러온다.
infoTitle.forEach(function(e: any) {
var w = e.offsetWidth + 10;
e.parentElement.style.width = w;
e.parentElement.style.position = "relative";
if (e.className.includes('inactive')){
e.parentElement.previousSibling.style.backgroundImage = "url('https://user-images.githubusercontent.com/81412212/174342201-0ec0c927-97f1-49dd-8c23-d6a872d9dfad.png')"; //꼭지
} else {
e.parentElement.previousSibling.style.backgroundImage = "url('https://user-images.githubusercontent.com/81412212/174341207-bbaa6a46-2d67-4731-8a51-9a429488affa.png')"; //꼭지
}
e.parentElement.parentElement.style.display = "flex";
e.parentElement.parentElement.style.background = "none";
e.parentElement.parentElement.style.border = "none";
e.parentElement.parentElement.style.justifyContent = "center";
e.childNodes[1].style.display = "block";
e.childNodes[1].style.margin ="-8px";
e.parentElement.style.top = "-12px";
e.parentElement.style.top = "3px";
}
.infowindow를 선택하였기 때문에 e는
코드 (var inactiveInfoWindow)에 선언한 최상단 div이다.
e.parendElement는 그의 부모이며 인포윈도우 박스이다.
e.parendElement.previousSibling은 그의 앞쪽형제이고 인포윈도우 꼭지(V모양핀)이다.
e.parendElement.parentElement는 그의 조상이며 인포윈도우 박스+인포윈도우 꼭지(V모양핀부분)를 포함한다.
e.childNodes[n]은 그의 n번째 자식이며 여기선 span요소이다.
스타일은 .style
클릭이벤트는 .onclick 등 으로 설정할 수 있다.
e.parentElement.parentElement.onclick = handleIwClick //인포윈도우 클릭이벤트
...
function handleIwClick(e: any) {
console.log(e.target);
}
https://apis.map.kakao.com/web/sample/keywordBasic/