도영스 공간

리액트에서 지도 @react-google-maps/api 라이브러리 사용하여 (TypeScript + Next 환경) 본문

TIL/2022 TIL

리액트에서 지도 @react-google-maps/api 라이브러리 사용하여 (TypeScript + Next 환경)

dogdogdodo 2022. 12. 28. 23:56
반응형

오랜만에 적어보는 TIL ...🧘🏻‍♀️

 

구글 api key 설정하는 글들은 많으니 생략하겠습니다.

 

맨처음에는

리액트 환경에서 구글 map 자바스크립트 api 튜토리얼을 보고, 어떻게 해서든 구현하고 싶었다.

 

하지만, 내가 구현해야되는 기능은 n초마다 나의 위치 정보를 서버에 갱신해주고

내 주위 3km 반경에 있는 사람들의 좌표를 구글 맵에서 마커로 찍어주는 것이었다.

 

라이브러리를 깔지 않고 ,, 시도한 결과

n초마다 내 위치를 갱신할때마다 나의 위치를 찍어주는 마커가 계속 생성되는 것이었다..ㅠㅠ

ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ일요일 하루종일 고민하며 코드를 써내려갔지만, ㅠㅠ 

나의 위치 정보를 제대로 반영하면, 지도가 깜빡거리는 문제가 발생했다 ㅎ..

 

결국 자바스크립트 튜토리얼로는 해결할 수 없겠다는 생각이 들었다.

그렇게 내가 깐 라이브러리는 2개

한개는 타입스크립트 환경을 위한 타입!

또 하나는 react-google-maps/api라는 라이브러리당!

npm i -D @types/google.maps
npm i @react-google-maps/api

 

구글맵에서 발급받은 api key를 env 환경에 잘 저장해주고,

import {
	Circle,
	GoogleMap,
	Marker,
	useLoadScript,
} from '@react-google-maps/api';
const Map = (props: PropsType) => {
	

	const [center, setCenter] = useState({
		lat: 0,
		lng: 0,
	}); //map center
	const [myLocation, setMyLocation] = useState({
		lat: 0,
		lng: 0,
	});
	const [zoom, setZoom] = useState(14); //map zoom level
	
	const [map, setMap] = useState(null); //map state

	
	//map 스크립트에 key 넣어줌
	const { isLoaded } = useLoadScript({
		googleMapsApiKey: 이곳에 google api key를 넣어줍니다,
		id: 'google-map-script',
	});
    
	//지도 로드 되자마자 실행되는 함수
	const onLoad = useCallback((map) => {
		const bounds = new window.google.maps.LatLngBounds(center);
		map.fitBounds(bounds);
		setMap(map);
	}, []);
	//지도 꺼졌을 때 실행되는 함수
	const onUnmount = useCallback((map) => {
		setMap(null);
	}, []);


	//내위치로 돌아가기 버튼 클릭
	const onClickGeoLocation = () => {
		if (navigator.geolocation) {
			navigator.geolocation.getCurrentPosition(
				async (position: GeolocationPosition) => {
					const pos = {
						lat: position.coords.latitude,
						lng: position.coords.longitude,
					};
					setCenter(pos);
					setMyLocation(pos);
					setZoom(15);
					
				},
				(err) => {
					console.log(err);
					popup.alert('위치 정보를 허용해주세요!');
				},
			);
		} else {
			// Browser doesn't support Geolocation
			popup.alert('브라우저에서 위치 정보를 허용해주세요!');
		}
	};

	
	//zoom change
	const mapZoomChange = () => {
		setZoom(map?.getZoom()); //map zoom 확대 축소 이벤트 일어날 때마다 map의 줌레벨 setting
	};
	//지도 스타일링
	const containerStyle = {
		width: '100%',
		height: `100vh`,//화면에 지도가 꽉찬다. => 싫다면 px로 조절
	};
	// 지도 옵션
	const options = {
		minZoom: 4,//최소줌 지도레벨
		maxZoom: 18,//최대줌 지도레벨
		mapTypeControl: false, //구글맵 왼쪽 상단 지도,위성 전환 버튼 비활성화
		panControl: false, //이동 컨트롤 비활성화
		zoomControl: false, //scaleControl
		scaleControl: false, //지도 축척을 제공하는 Scale 컨트롤 비활성화
		fullscreenControl: false, //full 스크린 비활성화
		streetViewControl: false, //pegMan아이콘 street view 비활성화
		gestureHandling: 'greedy', //한손가락으로 지도 이동
		clickableIcons: false, //기본 마커 인포 윈도우 비활성화
	};
	//3km반경 표시해주는 원 옵션
	const circleOptions = {
		strokeColor: '#C5F1E0',
		strokeOpacity: 0.5,
		strokeWeight: 0,
		fillColor: '#C5F1E0',
		fillOpacity: 0.5,
		radius: 3000,// => 3km
	};

	return (
		<>
			<Styled.Wrap>
				
				{isLoaded ? (
					<>
						<GoogleMap
							mapContainerStyle={containerStyle}
							center={center}
							onUnmount={onUnmount}
							onLoad={onLoad}
							zoom={zoom}
							options={options}
							onZoomChanged={mapZoomChange}
							onClick={onClickAddMarker}>
							{zoom > 11 ? (
								<>
									<Marker
										position={myLocation}
										icon={'이미지 url'}
									/>
									<Circle
										center={myLocation}
										options={circleOptions}
										onClick={onClickAddMarker}
									/>
								</>
							) : null}
							<Styled.MapFocusIconWrap onClick={onClickGeoLocation}>
								<Icon.Focus />
							</Styled.MapFocusIconWrap>
						</GoogleMap>
					</>
				) : null}
				
			</Styled.Wrap>
			
		</>
	);
};

export default Map;

이렇게만 해준 뒤 geolocation 함수만 setInterval로 n초마다 실행시킨다면,, n초마다 나의 실시간 위치를 지도에서 띄워준다 !!

728x90
반응형
Comments