最近项目中有此需求,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>

截图示例如下:

1.png
2.png

标签: none

添加新评论

选择表情