在页面中,当填写地址信息时,需要动态展示下拉的相关地址信息,当选中某一地址信息,右边则展示地图,即相应的位置。前端使用的是React 以及Yarn

在前端需要添加插件: yarn add react-places-autocomplete(npm install react-places-autocomplete)

在你的页面中导入Location.jsx组件

 Location.jsx

import React from 'react';
import { Card, Checkbox, Col, Row, Form, Input } from 'antd';
import loadable from 'loadable-components';
import has from 'has';
import { geocodeByAddress, getLatLng } from 'react-places-autocomplete';
import PropTypes from 'prop-types';
import { FIELD_MAX_LENGTH } from 'App/Jobs/PostJob/Constants';
import './Location.scss';const GoogleMap = loadable(() => import(/* webpackChunkName: "GoogleMap" */'App/Jobs/PostJob/Components/JobInfo/GoogleMap'));
const LocationSearchInput = loadable(() => import(/* webpackChunkName: "LocationSearchInput" */'App/Jobs/PostJob/Components/JobInfo/LocationSearchInput'));class Location extends React.PureComponent {state = {showApplicant: has(this.props.jobDetail, 'showApplicant') ? this.props.jobDetail.showApplicant : false,remote: has(this.props.jobDetail, 'remote') ? this.props.jobDetail.remote : false,longitude: this.props.jobDetail.longitude || 0,latitude: this.props.jobDetail.latitude || 0,mapReady: false,};handleCheckShowApplicant = (e) => {const { form: { setFieldsValue } } = this.props;const showApplicant = e.target.checked;this.setState({ showApplicant }, setFieldsValue({ showApplicant }));}handleCheckRemote = (e) => {const { form: { setFieldsValue } } = this.props;const remote = e.target.checked;this.setState({ remote }, setFieldsValue({ remote }));}handleGetLocation = () => {const { form: { getFieldsValue } } = this.props;let location = '';const {streetAddress, city, state, zipCode,} = getFieldsValue();if (city && state) {location = `${streetAddress}, ${city}, ${state}, ${zipCode}`;location = location.replace(/^, |, $/g, '');}return location;}handleChange = () => {const { form: { setFieldsValue } } = this.props;const location = this.handleGetLocation();setFieldsValue({ location });if (location === '') {return;}if (this.state.mapReady) {geocodeByAddress(location).then(results => getLatLng(results[0])).then((latLng) => {this.setState({longitude: latLng.lng,latitude: latLng.lat,});setFieldsValue({longitude: latLng.lng,latitude: latLng.lat,});}).catch(() => false);}}handleMapReady = () => this.setState({ mapReady: true })render() {const {form, jobDetail, locationIntro, handleWhichTipShow,} = this.props;const { getFieldDecorator } = form;const {showApplicant, longitude, latitude, remote, mapReady,} = this.state;return (<Row><Col span={15}><div className="postjob-location"><div className="title">Job location</div><Form.Item label="Street Address"><LocationSearchInputstreetAddress={jobDetail.streetAddress || ''}handlelocation={this.handleChange}form={form}handleAskButtonClick={() => handleWhichTipShow(false, false, !locationIntro)}handleFocus={() => handleWhichTipShow(false, false, false)}handleMouseOver={() => handleWhichTipShow(false, false, true)}handleMouseOut={() => handleWhichTipShow(false, false, false)}locationIntro={locationIntro}mapReady={mapReady}/></Form.Item><div className="location-style"><Form.Item label="City" className="address-inline">{getFieldDecorator('city', {initialValue: jobDetail.city || '',rules: [{ required: true, message: 'City is required.', whitespace: true }],validateTrigger: ['onChange'],})(<Inputsize="large"placeholder="City"onFocus={() => handleWhichTipShow(false, false, false)}onMouseOver={() => handleWhichTipShow(false, false, true)}onMouseOut={() => handleWhichTipShow(false, false, false)}onBlur={() => handleWhichTipShow(false, false, false)}onKeyUp={this.handleChange}maxLength={FIELD_MAX_LENGTH.LOCATION}/>)}</Form.Item><Form.Item label="State" className="address-inline">{getFieldDecorator('state', {initialValue: jobDetail.state || '',rules: [{ required: true, message: 'State is required.', whitespace: true }],validateTrigger: ['onChange'],})(<Inputsize="large"placeholder="State"onFocus={() => handleWhichTipShow(false, false, false)}onMouseOver={() => handleWhichTipShow(false, false, true)}onMouseOut={() => handleWhichTipShow(false, false, false)}onBlur={() => handleWhichTipShow(false, false, false)}onKeyUp={this.handleChange}maxLength={FIELD_MAX_LENGTH.LOCATION}/>)}</Form.Item><Form.Item label="ZipCode" className="address-inline">{getFieldDecorator('zipCode', {initialValue: jobDetail.zipCode || '',})(<Inputsize="large"placeholder="ZipCode"onFocus={() => handleWhichTipShow(false, false, false)}onMouseOver={() => handleWhichTipShow(false, false, true)}onMouseOut={() => handleWhichTipShow(false, false, false)}onBlur={() => handleWhichTipShow(false, false, false)}onKeyUp={this.handleChange}maxLength={FIELD_MAX_LENGTH.LOCATION}/>)}</Form.Item></div></div><Form.Item className="checkbox-position checkbox-first"><Checkbox checked={remote} onChange={this.handleCheckRemote} disabled={showApplicant}>This is a Telecommute/Work from Home position</Checkbox></Form.Item><Form.Item className="checkbox-position"><Checkboxchecked={remote ? false : showApplicant}onChange={this.handleCheckShowApplicant}disabled={remote}>Only show me applicants within 100 miles of this location</Checkbox></Form.Item></Col><Col span={9}><Card className="google-map-layer">{locationIntro &&<p>Location is used to find job seekers near you.You can hide your address, but city and state will still be visible.</p>}<GoogleMapform={form}longitude={longitude}latitude={latitude}handleMapReady={this.handleMapReady}/></Card></Col><div className="postjob-register-hidden-form"><Form.Item>{getFieldDecorator('latitude', { initialValue: jobDetail.latitude })(<div />)}</Form.Item><Form.Item>{getFieldDecorator('longitude', { initialValue: jobDetail.longitude })(<div />)}</Form.Item><Form.Item>{getFieldDecorator('remote', { initialValue: jobDetail.remote })(<div />)}</Form.Item><Form.Item>{getFieldDecorator('showApplicant', { initialValue: jobDetail.showApplicant })(<div />)}</Form.Item><Form.Item>{getFieldDecorator('location', { initialValue: jobDetail.location })(<div />)}</Form.Item></div></Row>);}
}Location.propTypes = {form: PropTypes.shape().isRequired,locationIntro: PropTypes.bool.isRequired,handleWhichTipShow: PropTypes.func.isRequired,jobDetail: PropTypes.shape().isRequired,
};export default Location;

 GoogleMap.jsx

import React from 'react';
import loadJs from 'loadjs';
import loadGoogleMap from 'App/Common/Utils/LoadGoogleMap';
import PropTypes from 'prop-types';
import isNumber from 'App/Common/Utils/CheckVariableType';let marker;
let map;class GoogleMap extends React.Component {state = { isMapInit: false };componentDidMount() {loadGoogleMap();const { form } = this.props;const lat = form.getFieldValue('latitude');const lng = form.getFieldValue('longitude');this.initGoogleMap(lat, lng);}componentWillReceiveProps(nextProps) {const { latitude, longitude } = nextProps;const { isMapInit } = this.state;if (this.props.latitude !== latitude || this.props.longitude !== longitude) {if (!isMapInit) {this.initGoogleMap(latitude, longitude);} else {if (marker) {marker.setMap(null);}map.setCenter({ lat: latitude, lng: longitude });marker = new window.google.maps.Marker({position: new window.google.maps.LatLng(latitude, longitude),map,});}}}setupMapDom = (element) => {this.mapRef = element;}initGoogleMap = (lat, lng) => {loadJs.ready('googleMap', () => {this.props.handleMapReady();if (isNumber(lat) && isNumber(lng)) {map = new window.google.maps.Map(this.mapRef, {zoom: 15,mapTypeControl: false,zoomControl: true,streetViewControl: false,fullscreenControl: false,});map.setCenter({ lat, lng });marker = new window.google.maps.Marker({position: new window.google.maps.LatLng(lat, lng),map,});this.addMapMarkerListener();this.setState({ isMapInit: true });}});}addMapMarkerListener = () => {map.addListener('click', (e) => {const { form } = this.props;if (marker) {marker.setMap(null);}marker = new window.google.maps.Marker({position: new window.google.maps.LatLng(e.latLng.lat(), e.latLng.lng()),map,});form.setFieldsValue({latitude: e.latLng.lat(),longitude: e.latLng.lng(),});});}render() {return (<divref={(element) => {this.setupMapDom(element);}}id="map"/>);}
}GoogleMap.propTypes = {form: PropTypes.shape().isRequired,latitude: PropTypes.number.isRequired,longitude: PropTypes.number.isRequired,handleMapReady: PropTypes.func.isRequired,
};export default GoogleMap;

LocationSearchInput.jsx

import React from 'react';
import PlacesAutocomplete, { geocodeByAddress } from 'react-places-autocomplete';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { Input, Button } from 'antd';
import notification from 'App/Common/Utils/Notification';
import { FIELD_MAX_LENGTH } from 'App/Jobs/PostJob/Constants';
import './LocationSearchInput.scss';class LocationSearchInput extends React.Component {state = {streetAddress: this.props.streetAddress,isFetchSuggestions: false,};componentWillReceiveProps(nextProps) {const { mapReady, form } = nextProps;if (mapReady) {this.setState({ streetAddress: form.getFieldValue('streetAddress') || '' });}}onLocationFocus =() => {this.props.handleFocus();this.setState({ isFetchSuggestions: true });}onLocationBlur = () => {this.setState({ isFetchSuggestions: false });}onError = (status, clearSuggestions) => {// eslint-disable-next-line no-consoleconsole.warn('Google Maps API returned error with status: ', status);clearSuggestions();}handleSelect = (address) => {const { handlelocation, form } = this.props;let city = '';let state = '';let zipCode = '';let route = '';let streetNumber = '';geocodeByAddress(address).then((results) => {results[0].address_components.forEach((value) => {switch (value.types[0]) {case 'administrative_area_level_1': state = value.long_name;break;case 'locality': city = value.long_name;break;case 'postal_code': zipCode = value.long_name;break;case 'route': route = value.long_name;break;case 'street_number': streetNumber = value.long_name;break;default: break;}});const streetAddress = `${streetNumber} ${route}`.replace(/^ /, '') || '';this.setState({ streetAddress });form.setFieldsValue({streetAddress,city,state,zipCode,}, handlelocation);}).catch(err => notification('err', 'Error', err));};handleChange = (streetAddress) => {const { handlelocation } = this.props;this.setState({ streetAddress });this.props.form.setFieldsValue({streetAddress,}, handlelocation);};render() {const { isFetchSuggestions, streetAddress } = this.state;const {mapReady, handleAskButtonClick, handleMouseOver, handleMouseOut,locationIntro, form, handleFocus,} = this.props;return (<div className="location_input">{!mapReady ?<div className="street-address-for-google-failed-div">{form.getFieldDecorator('streetAddress', {initialValue: streetAddress || '',})(<InputclassName="street-address-for-google-failed"onFocus={handleFocus}onBlur={handleMouseOut}onMouseOver={handleMouseOver}onMouseOut={handleMouseOut}maxLength={FIELD_MAX_LENGTH.LOCATION}/>)}</div> :<PlacesAutocompletevalue={this.state.streetAddress}onChange={this.handleChange}onSelect={this.handleSelect}shouldFetchSuggestions={isFetchSuggestions}highlightFirstSuggestiononError={this.onError}>{({getInputProps, suggestions, getSuggestionItemProps, loading,}) => (<div className="autocomplete-place-input"><Inputsize="large"{...getInputProps({className: 'location-search-input',})}className="location-box"onBlur={this.onLocationBlur}value={streetAddress}onFocus={this.onLocationFocus}onMouseOver={handleMouseOver}onMouseOut={() => handleMouseOut()}maxLength={FIELD_MAX_LENGTH.LOCATION}/><div hidden={!isFetchSuggestions || suggestions.length === 0} className={suggestions.length === 0 ? 'autocomplete-dropdown-container' : 'autocomplete-dropdown-container autocomplete-dropdown-border'}>{loading && <div>Loading...</div>}{suggestions.map((suggestion) => {const className = suggestion.active? 'suggestion-item--active': 'suggestion-item';// inline style for demonstration purposeconst style = suggestion.active? { backgroundColor: '#fafafa', cursor: 'pointer' }: { backgroundColor: '#ffffff', cursor: 'pointer' };return (<div{...getSuggestionItemProps(suggestion, {className,style,})}><span>{suggestion.description}</span></div>);})}</div>{form.getFieldDecorator('streetAddress', {initialValue: streetAddress || '',})(<Input hidden />)}</div>)}</PlacesAutocomplete>}&nbsp;&nbsp;&nbsp;<Button className={classnames('ask-button', 'location-ask-button', { selected: locationIntro })} shape="circle" onClick={handleAskButtonClick}>?</Button></div>);}
}LocationSearchInput.propTypes = {form: PropTypes.shape({getFieldValue: PropTypes.func.isRequired,getFieldDecorator: PropTypes.func.isRequired,setFieldsValue: PropTypes.func.isRequired,}).isRequired,handlelocation: PropTypes.func.isRequired,handleAskButtonClick: PropTypes.func.isRequired,handleFocus: PropTypes.func.isRequired,handleMouseOver: PropTypes.func.isRequired,handleMouseOut: PropTypes.func.isRequired,locationIntro: PropTypes.bool.isRequired,streetAddress: PropTypes.string.isRequired,
};export default LocationSearchInput;

LoadGoogleMap.js

该文件需要GOOGLE_MAP_KEY的值

import loadJs from 'loadjs';export default function loadGoogleMap() {if (!loadJs.isDefined('googleMap') && typeof GOOGLE_MAP_KEY === 'string') {loadJs(`https://maps.googleapis.com/maps/api/js?key=${GOOGLE_MAP_KEY}&libraries=places`, 'googleMap');}
}

React google map相关推荐

  1. 2021年在vue中使用 Google Map

    目前在vue中使用google map有以下两种方法: 一.使用 JavaScript 创建地图实例 该方法优点在于可配置项多,方便自定义,缺点是较复杂,且文档为英文,有一定学习难度. 在开始之前确保 ...

  2. google map api v3 的marker使用label的方法(markerwithlabel的使用)

    简介 公司有个需求就是需要实现在marker下面显示标题的名称,百度地图api里面这些东西都有,但是google查了一遍api,却没有找到,通过搜索发现了markerwithlabel这样一个组件,能 ...

  3. Android特色开发之Google MAP

    本文节选于机械工业出版社推出的<Android应用开发揭秘>一书,作者为杨丰盛.本书内容全面,详细讲解了Android框架.Android组件.用户界面开发.游戏开发.数据存储.多媒体开发 ...

  4. 关于Google Map API V2 版本的定位与导航

    近来,在关注安卓手机上的GoogleMap应用的开发,但是目前官方API版本网页版已经升级到V3版,而对于Android的支持也已经升级到V2版本,虽然Google说继续对V1版提供服务,但是不再提供 ...

  5. 分享两篇Google Map API的介绍

    这两篇文章也不知道我是什么时候下载下来的,一直丢在桌面上没有看,但终于在年后无聊就看了一下,结果让我心潮澎湃,一起哈成了"都让Google做了我们还做什么?(WebMap方向)"一 ...

  6. Google Map App 问题集锦

    用此帖记录做Google Map过程中遇到的问题. 一.因为在Manifest.xml文件没有写入<service>,所以导致启动不了Service,但是我明明写了啊.后来发现是自己为了版 ...

  7. 如何在Android手机上进行Google Map的开发。

    1.题记 提起谷歌Map相信大家都不会陌生,那进入我们今天的话题,如何在Android手机上进行Google Map的开发. 2.Map应用程序的开发 2.1 准备工作 2.1.1 申请Android ...

  8. Google Map API 的基础使用

    因为公司业务由国内市场到国际市场,有一些国际性业务的项目需要用到Google Map.项目完成后,把一些常用的方法写出来,供大家参考. 一.google地图基础显示 (1)引用google map j ...

  9. 在你的Fckeditor安装Google map plugin

    Fckeditor是现在很常见的Html编辑器,他好用的地方除了很方便引用外,还有就是他有一大推好用的plug in可以用,像是点部落使用的code highlight,就是plug in上去的功能. ...

最新文章

  1. ​EMC存储产品介绍分析(二):大数据利器Isilon (1)
  2. bios文件查看工具_修改BIOS让老主板支持NVMe固态硬盘
  3. windows如何调整某个应用程序的音量 c++_微软对重启Windows 10的应用程序进行控制测试...
  4. 前端绘制绘制图表_绘制图表(第2页):JavaScript图表库的比较
  5. exit(),_exit()的区别
  6. 从工程文化和运维理念理解Netflix
  7. 安装WPS办公软件后广告特别多怎么办?【wps广告】全网最详细!!!
  8. Android通过AIDL与远程服务通信
  9. Linux 命令查询工具
  10. swift的if语句
  11. 我用九天时间,深挖一条闲鱼诈骗黑色产业链。
  12. 软件测试团队队名,电子设计大赛队名
  13. Python 正则表达式大全
  14. php遍历桌面上的记事本,电脑桌面显示记事本便签内容要怎么设置一直锁定在桌面?...
  15. xshell5和xftp5安装教程
  16. selector wakeup
  17. C语言fflush方法
  18. 5G助推全球新经济变革,十万亿产业研讨盛会等你来
  19. ASP 模板引擎,ASP 模板类 (Taihom.Template.class)
  20. PAT乙级真题1058 || 选择题(详解,C/C++示例,测试点分析)

热门文章

  1. 非标机械设计工艺讲解视频教程 机加 焊接 热处理 装配教程
  2. 关于游戏服务器运营商改如何做出选择
  3. 关于相关国企央企求职心得
  4. JDK1.6.0新特性详解与代码示例 - 徐明明的博客 - CSDNBlog
  5. Ubuntu 13.04 系统管理初探
  6. RecyclerView使用static和不使用static的Viewholder内存消耗相差无几
  7. Asce‘s Summer Ranking No.11
  8. zcmu 1919 kirito's 星爆气流斩(多重背包转01背包,并且进行2进制优化)
  9. 中国银行支付接口(ecshop版)
  10. 普通工厂类和抽象工厂类的区别