最近项目中有此需求,react地图组件的开发:
1 输入地址可查询出对应地图位置并标记点
2 能返回经纬度,并提交服务端保存
3 在地图上点击某一点,也能返回对应经纬度和地址信息
4 国内,国外均可使用
经过调研决定,采用谷歌地图和高德地图来封装组件,当渲染地图组件时,先试图请求谷歌map的api,
若能访问则使用谷歌地图,若不能访问,则调用国内高德地图,
框架环境:react+dva+antd+umiJs;其中需要用到prop-types,axios,scriptjs,对应npm安装即可。
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>
截图示例如下: