react地图组件


最近项目中有此需求,react地图组件的开发:
1 输入地址可查询出对应地图位置并标记点
2 能返回经纬度,并提交服务端保存
3 在地图上点击某一点,也能返回对应经纬度和地址信息
4 国内,国外均可使用

经过调研决定,采用谷歌地图和高德地图来封装组件,当渲染地图组件时,先试图请求谷歌map的api,
若能访问则使用谷歌地图,若不能访问,则调用国内高德地图,

框架环境:react+dva+antd+umiJs;其中需要用到prop-types,axios,scriptjs,对应npm安装即可。

具体组件如下:

import React from 'react'
import PropTypes from 'prop-types'
import { Spin } from 'antd';
import axios from 'axios';
import $script from 'scriptjs'
import styles from './AMap.less'

const googleMapSdk='https://maps.googleapis.com/maps/api/js?key=your key';
const gaodeMapSdk='https://webapi.amap.com/maps?v=1.4.2&key=your key';

let map = null;
let marker = null;
let geocoder = null;
let zoomLevel=15;

class AMapModule extends React.Component {
  constructor(props){
    super(props); 
    this.state = {
      status:0
    };   
  }
  componentWillMount(){
    if(!window.AMap&&!(window.google&&window.google.maps)){
      axios.get(googleMapSdk,{timeout: 1000}).then(res => {
            $script( [googleMapSdk],function(a,b){})
          }).catch(function (error) {
            $script( [gaodeMapSdk],function(a,b){})
      }); 
    }
  }
  componentDidMount(){
    let _this=this;
    function listenerStorage(){
      if(window.AMap||(window.google && window.google.maps)){
        if(window.AMap) {
          const {lat, lng, getMapAddress} = _this.props;
          const latlngxy=[(!lng||lng=='undefined'||lng=='0')?116.397428:lng,(!lat||lat=='undefined'||lat=='0')?39.90923:lat];//默认北京天安门
          map = new window.AMap.Map('allmap', {
              resizeEnable: true,
              center: latlngxy,
              zoom: zoomLevel
            });
            
          //高德设置语言    ['en', 'zh_en', 'zh_cn']
          let mapLang;
          if(window.localStorage.getItem('i18n') == 'en_US'){
            mapLang = 'en';
          }else{
            mapLang = 'zh_cn';
          }     
          map.setLang(mapLang);
    
          // 在新中心点添加 marker 
          marker = new window.AMap.Marker({
              map: map,
              position: latlngxy
          });
    
          map.on('click',function(e){
            marker.setPosition(e.lnglat);
            window.AMap.service('AMap.Geocoder',function(){//回调函数
              //实例化Geocoder
              geocoder = new window.AMap.Geocoder({});
              geocoder.getAddress(e.lnglat,function(status,result){
                if(status === 'complete' && result.info === 'OK'){
                  const address=result.regeocode.formattedAddress
                  getMapAddress&&getMapAddress(address);
                }
              })
            })
          })
        }
    
        if(window.google && window.google.maps){
    
          const {lat, lng, getMapAddress} = _this.props;
          const latlngxy=[(!lng||lng=='undefined'||lng=='0')?116.397428:lng,(!lat||lat=='undefined'||lat=='0')?39.90923:lat];//默认北京天安门
     
          var uluru = {lat: parseFloat(latlngxy[1]), lng: parseFloat(latlngxy[0])};  // google need number
    
          initMap()
          function initMap() {
            map = new window.google.maps.Map(document.getElementById('allmap'), {
                resizeEnable: true,
                center: uluru,
                zoom: zoomLevel
            });
            // 在新中心点添加 marker 
            marker = new window.google.maps.Marker({
                map: map,
                position: uluru
            });
          }
    
          map.addListener('click',function(e){
            let latlng=e.latLng;
            marker.setPosition(latlng);
            geocoder = new window.google.maps.Geocoder()
            geocoder.geocode({'location': latlng}, function(results, status) {
              if (status === 'OK') {
                const address=results[0].formatted_address
                getMapAddress&&getMapAddress(address.substring(0,address.indexOf(' ')));
              } else {
                console.log('Geocoder failed due to: ' + status);
              }
            });
          })
        }
        _this.setState({
          status:1
        })
      }else{
        setTimeout(function(){
          listenerStorage()
        },800)
      }
    }
    listenerStorage();
  }

  componentWillReceiveProps=(nextProps)=>{
    const {getMapPoint}=this.props;
    if(window.AMap && nextProps.address&&nextProps.address!=this.props.address) {
      window.AMap.service('AMap.Geocoder',function(){//回调函数
          //实例化Geocoder
          geocoder = new window.AMap.Geocoder({});
          geocoder.getLocation(nextProps.address, function (status, result) {
            if (status === 'complete' && result.info === 'OK') {
              let latlng = result.geocodes[0].location;
              getMapPoint&&getMapPoint(latlng);
              // 设置缩放级别和中心点
              let latlngxy = [latlng['lng'],latlng['lat']];
              const currentZoom=map.getZoom();
              map.setZoomAndCenter(currentZoom!=zoomLevel?currentZoom:zoomLevel, latlngxy);
              // 在新中心点添加 marker 
              marker.setPosition(latlng);
            } else {
              console.log('search "' + nextProps.address + '" no data')
            }
          });
      });
    }

    if(window.google && window.google.maps && nextProps.address&&nextProps.address!=this.props.address){
      geocoder = new window.google.maps.Geocoder()
      geocoder.geocode({'address': nextProps.address}, function(results, status) {
        if (status === 'OK') {
          let latlng = results[0].geometry.location;
          getMapPoint&&getMapPoint({lat:latlng.lat(),lng:latlng.lng()});
          map.setCenter(latlng);
          // 在新中心点添加 marker 
          marker.setPosition(latlng);
        } else {
          console.log('Geocode was not successful for the following reason: ' + status);
        }
      });
    }
  }
 
  render(){
    const { height } = this.props;
    return(
      <div className={styles.container} style={{height:height?height:300}}>
        <Spin spinning={this.state.status==0?true:false} tip="Loading...">
          <div id="allmap" className={styles.mapContainer} style={{height:height?height:300}} />
        </Spin>
      </div>
    )
  }
}

AMapModule.propTypes = {
  lng: PropTypes.string,
  lat: PropTypes.string,
  className: PropTypes.string,
}

export default AMapModule            

调用如下:

<div style={{width:'500px'}}>
            <Form>
                <FormItem
                          label={
                            <span>
                              地址
                            </span>
                          }>
                          {getFieldDecorator('position', {
                            initialValue: '北京'
                          })(
                            <Input placeholder={'请输入地址'} />
                            )}
                </FormItem>
                <FormItem
                label={
                    <span>
                      经度
                    </span>
                  }>
                              {getFieldDecorator('longitude', {
                                initialValue: ''
                              })(
                                <Input />
                                )}
                          </FormItem>
                          <FormItem label={
                    <span>
                      维度
                    </span>
                  }>
                              {getFieldDecorator('latitude', {
                                initialValue: ''
                              })(
                                <Input/>
                                )}
                </FormItem>
                
                    <AMap 
                        lng={''}
                        lat={''}
                        address={getFieldValue('position')}
                        getMapPoint={(point)=>{
                            setFieldsValue({
                                latitude: point.lat,
                                longitude: point.lng
                            });
                        }}
                        getMapAddress={(address)=>{
                            setFieldsValue({
                                position: address
                            });
                        }}
                    />
                
            </Form>
            </div>

截图示例如下:



猜你喜欢

转载自blog.csdn.net/xw505501936/article/details/80580081
今日推荐