Google Map

16458 단어 React후크
오늘부터 3일간은 외부 API나 media element를 이용한 바뀌어 Dane를 소개합니다. 오늘은 Google Map을 포함하고 현재 위치를 표시하는 샘플입니다. $ yarn 1219 한 것만으로는 거동 확인을 할 수 없으므로, 이하 순서로 셋업하고 나서 시험해 주세요.
code: github/$ yarn 1219






setup


  • Maps JavaScript API의 API 키 가져 오기
  • 키에 응용 프로그램 제한을 적용합니다 (http://localhost:1234/ 등)
  • 키에 API 제한 적용(Maps JavaScript API)


  • Google Map API를 사용하려면 api_key가 필요합니다. 환경 변수에서 script tag에 api_key를 삽입합니다. 리포지토리 루트에 .env를 만들고 얻은 api_key를 넣습니다.
    GOOGLE_MAP_API_KEY=XXXXXX
    

    샘플에는 parcel을 사용하고 react-async-script로 환경 변수에서 script 태그를 생성합니다 (parcel의 경우).

    app.tsx
    import * as React from 'react'
    import { render } from 'react-dom'
    import Root from './components/index'
    // @ts-ignore
    import makeAsyncScriptLoader from 'react-async-script'
    const URL = `https://maps.googleapis.com/maps/api/js?key=${
      process.env.GOOGLE_MAP_API_KEY
    }`
    const AsyncScriptRoot = makeAsyncScriptLoader(URL)(Root)
    render(<AsyncScriptRoot />, document.getElementById('app'))
    

    진행 상황에 따른 View 분기



    geolocation API를 사용하여 사용자의 현재 위치를 사용합니다. 현재 위치를 얻을 수 있을 때까지 3개의 View로 분기합니다.

    components/index.tsx
    export default () => (
      <GeolocationWrapper
        renderProcessView={() => <ProcessView />}
        renderSuccessView={coords => (
          <GoogleMapView coords={coords} />
        )}
        renderErrorView={() => <ErrorView />}
      />
    )
    
    navigator.geolocation.getCurrentPosition 를 call 하면, 현재 위치 취득의 허가가 요구됩니다. 현재 위치도 에러도 null 이면 진행중의 View 를, 에러가 있으면 에러 View 를, 현재 위치 취득이 할 수 있으면 GoogleMap API 이용의 View 를 마운트합니다.

    components/geolocationWrapper.tsx
    export default (props: Props) => {
      const [coords, setCoords] = useState<Coordinates | null>(
        null
      )
      const [error, setError] = useState<PositionError | null>(
        null
      )
      useEffect(() => {
        navigator.geolocation.getCurrentPosition(
          ({ coords }) => {
            setCoords(coords)
          },
          setError
        )
      }, [])
      return (
        <>
          {useMemo(
            () => {
              if (coords === null) return
              return props.renderSuccessView(coords)
            },
            [coords]
          )}
          {useMemo(
            () => {
              if (error === null) return
              return props.renderErrorView(error)
            },
            [error]
          )}
          {useMemo(
            () => {
              if (!(error === null && coords === null)) return
              return props.renderProcessView()
            },
            [coords, error]
          )}
        </>
      )
    }
    

    useEffect 및 GoogleMap API



    GoogleMap API에 따라 마운트 중에 얻은 현재 위치 coords로 API를 치십시오. 맵을 마운트하는 태그는 ref 로 참조해, API callback 시에 useState 의 갱신 함수로 재묘화 시킵니다.

    components/googleMapView.tsx
    const View = (props: Props) => {
      const [addressLabel, setAddressLabel] = useState(
        '...取得しています'
      )
      const ref = useRef({} as HTMLDivElement)
      useEffect(
        () => {
          if (ref.current === null) return
          const { latitude, longitude } = props.coords // 取得した現在位置
          const center = { lat: latitude, lng: longitude }
          const mapOptions: google.maps.MapOptions = {
            center,
            zoom: 16
          }
          const map = new google.maps.Map(
            ref.current,
            mapOptions
          )
          const markerOptions: google.maps.MarkerOptions = {
            position: center,
            map
          }
          new google.maps.Marker(markerOptions)
          const geocoder = new google.maps.Geocoder()
          geocoder.geocode({ location: center }, function(
            results,
            status
          ) {
            if (status == google.maps.GeocoderStatus.OK) {
              setAddressLabel(results[1].formatted_address)
            } else {
              setAddressLabel('取得に失敗しました')
            }
          })
        },
        [props.coords]
      )
      return (
        <div className={props.className}>
          <div className="map" ref={ref} />
          <p className="addressLabel">
            現在住所
            {addressLabel}
          </p>
        </div>
      )
    }
    
  • 좋은 웹페이지 즐겨찾기