티스토리 뷰

목차


    반응형

    오랜만에 적어보는 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
    반응형