React-google-maps 用户位置

Posted

技术标签:

【中文标题】React-google-maps 用户位置【英文标题】:React-google-maps user location 【发布时间】:2020-04-07 09:42:21 【问题描述】:

试图在我的反应应用程序中设置一个谷歌地图,该地图以用户位置为中心并返回地址。有人能告诉我如何编辑以下代码,以便地图和标记加载到用户位置。我知道如何设置地理位置,但似乎无法在不破坏现有代码的情况下做到这一点

地图组件

import React,  Component  from 'react';
import  withGoogleMap, GoogleMap, withScriptjs, InfoWindow, Marker  from "react-google-maps";
import Geocode from "react-geocode";
import Autocomplete from 'react-google-autocomplete';
Geocode.setApiKey( "googleAPIkey" );
Geocode.enableDebug();

class Map extends Component

    constructor( props )
        super( props );
        this.state = 
            address: '',
            city: '',
            area: '',
            state: '',
            mapPosition: 
                lat: this.props.center.lat,
                lng: this.props.center.lng
            ,
            markerPosition: 
                lat: this.props.center.lat,
                lng: this.props.center.lng
            
        
    
    /**
     * Get the current address from the default map position and set those values in the state
     */
    componentDidMount() 
        Geocode.fromLatLng( this.state.mapPosition.lat , this.state.mapPosition.lng ).then(
            response => 
                const address = response.results[0].formatted_address,
                      addressArray =  response.results[0].address_components,
                      city = this.getCity( addressArray ),
                      area = this.getArea( addressArray ),
                      state = this.getState( addressArray );

                console.log( 'city', city, area, state );

                this.setState( 
                    address: ( address ) ? address : '',
                    area: ( area ) ? area : '',
                    city: ( city ) ? city : '',
                    state: ( state ) ? state : '',
                 )
            ,
            error => 
                console.error( error );
            
        );
    ;
    /**
     * Component should only update ( meaning re-render ), when the user selects the address, or drags the pin
     *
     * @param nextProps
     * @param nextState
     * @return boolean
     */
    shouldComponentUpdate( nextProps, nextState )
        if (
            this.state.markerPosition.lat !== this.props.center.lat ||
            this.state.address !== nextState.address ||
            this.state.city !== nextState.city ||
            this.state.area !== nextState.area ||
            this.state.state !== nextState.state
        ) 
            return true
         else if ( this.props.center.lat === nextProps.center.lat )
            return false
        
    
    /**
     * Get the city and set the city input value to the one selected
     *
     * @param addressArray
     * @return string
     */
    getCity = ( addressArray ) => 
        let city = '';
        for( let i = 0; i < addressArray.length; i++ ) 
            if ( addressArray[ i ].types[0] && 'administrative_area_level_2' === addressArray[ i ].types[0] ) 
                city = addressArray[ i ].long_name;
                return city;
            
        
    ;
    /**
     * Get the area and set the area input value to the one selected
     *
     * @param addressArray
     * @return string
     */
    getArea = ( addressArray ) => 
        let area = '';
        for( let i = 0; i < addressArray.length; i++ ) 
            if ( addressArray[ i ].types[0]  ) 
                for ( let j = 0; j < addressArray[ i ].types.length; j++ ) 
                    if ( 'sublocality_level_1' === addressArray[ i ].types[j] || 'locality' === addressArray[ i ].types[j] ) 
                        area = addressArray[ i ].long_name;
                        return area;
                    
                
            
        
    ;
    /**
     * Get the address and set the address input value to the one selected
     *
     * @param addressArray
     * @return string
     */
    getState = ( addressArray ) => 
        let state = '';
        for( let i = 0; i < addressArray.length; i++ ) 
            for( let i = 0; i < addressArray.length; i++ ) 
                if ( addressArray[ i ].types[0] && 'administrative_area_level_1' === addressArray[ i ].types[0] ) 
                    state = addressArray[ i ].long_name;
                    return state;
                
            
        
    ;
    /**
     * And function for city,state and address input
     * @param event
     */
    onChange = ( event ) => 
        this.setState( [event.target.name]: event.target.value );
    ;
    /**
     * This Event triggers when the marker window is closed
     *
     * @param event
     */
    onInfoWindowClose = ( event ) => 

    ;

    /**
     * When the marker is dragged you get the lat and long using the functions available from event object.
     * Use geocode to get the address, city, area and state from the lat and lng positions.
     * And then set those values in the state.
     *
     * @param event
     */
    onMarkerDragEnd = ( event ) => 
        let newLat = event.latLng.lat(),
            newLng = event.latLng.lng();

        Geocode.fromLatLng( newLat , newLng ).then(
            response => 
                const address = response.results[0].formatted_address,
                      addressArray =  response.results[0].address_components,
                      city = this.getCity( addressArray ),
                      area = this.getArea( addressArray ),
                      state = this.getState( addressArray );
                this.setState( 
                    address: ( address ) ? address : '',
                    area: ( area ) ? area : '',
                    city: ( city ) ? city : '',
                    state: ( state ) ? state : '',
                    markerPosition: 
                        lat: newLat,
                        lng: newLng
                    ,
                    mapPosition: 
                        lat: newLat,
                        lng: newLng
                    ,
                 )
            ,
            error => 
                console.error(error);
            
        );
    ;

    /**
     * When the user types an address in the search box
     * @param place
     */
    onPlaceSelected = ( place ) => 
        console.log( 'plc', place );
        const address = place.formatted_address,
              addressArray =  place.address_components,
              city = this.getCity( addressArray ),
              area = this.getArea( addressArray ),
              state = this.getState( addressArray ),
              latValue = place.geometry.location.lat(),
              lngValue = place.geometry.location.lng();
        // Set these values in the state.
        this.setState(
            address: ( address ) ? address : '',
            area: ( area ) ? area : '',
            city: ( city ) ? city : '',
            state: ( state ) ? state : '',
            markerPosition: 
                lat: latValue,
                lng: lngValue
            ,
            mapPosition: 
                lat: latValue,
                lng: lngValue
            ,
        )
    ;


    render()
        const AsyncMap = withScriptjs(
            withGoogleMap(
                props => (
                    <GoogleMap google= this.props.google 
                               defaultZoom= this.props.zoom 
                               defaultCenter= lat: this.state.mapPosition.lat, lng: this.state.mapPosition.lng 
                    >
                        /* InfoWindow on top of marker */
                        <InfoWindow
                            onClose=this.onInfoWindowClose
                            position= lat: ( this.state.markerPosition.lat + 0.0018 ), lng: this.state.markerPosition.lng 
                        >
                            <div>
                                <span style= padding: 0, margin: 0 > this.state.address </span>
                            </div>
                        </InfoWindow>
                        /*Marker*/
                        <Marker google=this.props.google
                                name='Dolores park'
                                draggable=true
                                onDragEnd= this.onMarkerDragEnd 
                                position= lat: this.state.markerPosition.lat, lng: this.state.markerPosition.lng 
                        />
                        <Marker />
                        /* For Auto complete Search Box */

                    </GoogleMap>
                )
            )
        );
        let map;
        if( this.props.center.lat !== undefined ) 
            map = <div>
                <div>
                    <div className="form-group">
                        <label htmlFor="">City</label>
                        <input type="text" name="city" className="form-control" onChange= this.onChange  readOnly="readOnly" value= this.state.city />
                    </div>
                    <div className="form-group">
                        <label htmlFor="">Area</label>
                        <input type="text" name="area" className="form-control" onChange= this.onChange  readOnly="readOnly" value= this.state.area />
                    </div>
                    <div className="form-group">
                        <label htmlFor="">State</label>
                        <input type="text" name="state" className="form-control" onChange= this.onChange  readOnly="readOnly" value= this.state.state />
                    </div>
                    <div className="form-group">
                        <label htmlFor="">Address</label>
                        <input type="text" name="address" className="form-control" onChange= this.onChange  readOnly="readOnly" value= this.state.address />
                    </div>
                </div>

                <AsyncMap
                    googleMapURL="https://maps.googleapis.com/maps/api/js?key=googleAPIke"
                    loadingElement=
                        <div style= height: `100%`  />
                    
                    containerElement=
                        <div style= height: this.props.height  />
                    
                    mapElement=
                        <div style= height: `100%`  />
                    
                />
            </div>
         else 
            map = <div style=height: this.props.height />
        
        return( map )
    

export default Map

index.js 页面

import React,  Component  from 'react';
import Map from '../components/Map';

class Index extends Component 

    render() 
        return(
            <div style= margin: '100px' >
                <Map
                    google=this.props.google
                    center=lat: 18.5204, lng: 73.8567
                    height='300px'
                    zoom=15
                />
            </div>
        );
    


export default Index;```

【问题讨论】:

【参考方案1】:

..好吧,我想通了。可能不是最好的方法。但它有效。

import React,  Component  from 'react';
import Map from '../components/Map';
import CreateJob from '../components/CreateJob';

class Index extends Component 
    state =  userLocation:  lat: 32, lng: 32 , loading: true ;

  componentDidMount(props) 
    navigator.geolocation.getCurrentPosition(
      position => 
        const  latitude, longitude  = position.coords;

        this.setState(
          userLocation:  lat: latitude, lng: longitude ,
          loading: false
        );
      ,
      () => 
        this.setState( loading: false );
      
    );
  

  render() 
    const  loading, userLocation  = this.state;
    const  google  = this.props;

    if (loading) 
      return null;
    

        return(
      <div style= 
        margin: '0px',
      >
                <Map
                    google=this.props.google
                    center=userLocation
          height='350px'
          zoom=18         
                />
      <CreateJob />
            </div>

        );
    


export default Index;

【讨论】:

以上是关于React-google-maps 用户位置的主要内容,如果未能解决你的问题,请参考以下文章

React-Google-Maps 显示两个标记,一个在原始位置,另一个标记跟随地图的新中心 onDrag

当用户点击 react-google-maps 中的地图或标记时执行操作

使用react-google-maps刷新不需要的页面。

如何使用 react-google-maps 通过单击在地图上添加标记?

Reactjs react-google-maps 未定义

如何使用 react-google-maps 显示多个标记