React google map
在页面中,当填写地址信息时,需要动态展示下拉的相关地址信息,当选中某一地址信息,右边则展示地图,即相应的位置。前端使用的是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>} <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相关推荐
- 2021年在vue中使用 Google Map
目前在vue中使用google map有以下两种方法: 一.使用 JavaScript 创建地图实例 该方法优点在于可配置项多,方便自定义,缺点是较复杂,且文档为英文,有一定学习难度. 在开始之前确保 ...
- google map api v3 的marker使用label的方法(markerwithlabel的使用)
简介 公司有个需求就是需要实现在marker下面显示标题的名称,百度地图api里面这些东西都有,但是google查了一遍api,却没有找到,通过搜索发现了markerwithlabel这样一个组件,能 ...
- Android特色开发之Google MAP
本文节选于机械工业出版社推出的<Android应用开发揭秘>一书,作者为杨丰盛.本书内容全面,详细讲解了Android框架.Android组件.用户界面开发.游戏开发.数据存储.多媒体开发 ...
- 关于Google Map API V2 版本的定位与导航
近来,在关注安卓手机上的GoogleMap应用的开发,但是目前官方API版本网页版已经升级到V3版,而对于Android的支持也已经升级到V2版本,虽然Google说继续对V1版提供服务,但是不再提供 ...
- 分享两篇Google Map API的介绍
这两篇文章也不知道我是什么时候下载下来的,一直丢在桌面上没有看,但终于在年后无聊就看了一下,结果让我心潮澎湃,一起哈成了"都让Google做了我们还做什么?(WebMap方向)"一 ...
- Google Map App 问题集锦
用此帖记录做Google Map过程中遇到的问题. 一.因为在Manifest.xml文件没有写入<service>,所以导致启动不了Service,但是我明明写了啊.后来发现是自己为了版 ...
- 如何在Android手机上进行Google Map的开发。
1.题记 提起谷歌Map相信大家都不会陌生,那进入我们今天的话题,如何在Android手机上进行Google Map的开发. 2.Map应用程序的开发 2.1 准备工作 2.1.1 申请Android ...
- Google Map API 的基础使用
因为公司业务由国内市场到国际市场,有一些国际性业务的项目需要用到Google Map.项目完成后,把一些常用的方法写出来,供大家参考. 一.google地图基础显示 (1)引用google map j ...
- 在你的Fckeditor安装Google map plugin
Fckeditor是现在很常见的Html编辑器,他好用的地方除了很方便引用外,还有就是他有一大推好用的plug in可以用,像是点部落使用的code highlight,就是plug in上去的功能. ...
最新文章
- ​EMC存储产品介绍分析(二):大数据利器Isilon (1)
- bios文件查看工具_修改BIOS让老主板支持NVMe固态硬盘
- windows如何调整某个应用程序的音量 c++_微软对重启Windows 10的应用程序进行控制测试...
- 前端绘制绘制图表_绘制图表(第2页):JavaScript图表库的比较
- exit(),_exit()的区别
- 从工程文化和运维理念理解Netflix
- 安装WPS办公软件后广告特别多怎么办?【wps广告】全网最详细!!!
- Android通过AIDL与远程服务通信
- Linux 命令查询工具
- swift的if语句
- 我用九天时间,深挖一条闲鱼诈骗黑色产业链。
- 软件测试团队队名,电子设计大赛队名
- Python 正则表达式大全
- php遍历桌面上的记事本,电脑桌面显示记事本便签内容要怎么设置一直锁定在桌面?...
- xshell5和xftp5安装教程
- selector wakeup
- C语言fflush方法
- 5G助推全球新经济变革,十万亿产业研讨盛会等你来
- ASP 模板引擎,ASP 模板类 (Taihom.Template.class)
- PAT乙级真题1058 || 选择题(详解,C/C++示例,测试点分析)
热门文章
- 非标机械设计工艺讲解视频教程 机加 焊接 热处理 装配教程
- 关于游戏服务器运营商改如何做出选择
- 关于相关国企央企求职心得
- JDK1.6.0新特性详解与代码示例 - 徐明明的博客 - CSDNBlog
- Ubuntu 13.04 系统管理初探
- RecyclerView使用static和不使用static的Viewholder内存消耗相差无几
- Asce‘s Summer Ranking No.11
- zcmu 1919 kirito's 星爆气流斩(多重背包转01背包,并且进行2进制优化)
- 中国银行支付接口(ecshop版)
- 普通工厂类和抽象工厂类的区别