如何将Reaction与Google Places API结合使用,以在Google地图上显示位置标记?
我正在尝试构建一个与on Airbnb类似的地图,在其中您可以在拖动地图时查看位置标记。我要在地图上显示Google Places API中的酒店标记。
使用Google Maps中的以下JavaScript代码,我可以在Google地图上显示酒店,但我希望使用react-google-maps通过Reaction来实现这一点。
<!DOCTYPE html>
<html>
<head>
<title>Place searches</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
height: 100%;
margin: 0;
padding: 0;
}
</style>
<script>
// This example requires the Places library. Include the libraries=places
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places">
var map;
var infowindow;
function initMap() {
var pyrmont = {lat: -33.867, lng: 151.195};
map = new google.maps.Map(document.getElementById('map'), {
center: pyrmont,
zoom: 15
});
infowindow = new google.maps.InfoWindow();
var service = new google.maps.places.PlacesService(map);
service.nearbySearch({
location: pyrmont,
radius: 500,
type: ['hotel']
}, callback);
}
function callback(results, status) {
if (status === google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
createMarker(results[i]);
}
}
}
function createMarker(place) {
var placeLoc = place.geometry.location;
var marker = new google.maps.Marker({
map: map,
position: place.geometry.location
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(place.name);
infowindow.open(map, this);
});
}
</script>
</head>
<body>
<div id="map"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initMap" async defer></script>
</body>
</html>
react-google-maps有一个显示搜索输入字段的示例。这样,我就可以通过搜索来搜索并显示标记,例如,伦敦的酒店。但我不想搜索位置,而是想立即展示酒店的标记。(以下示例中的API密钥来自Reaction-Google-Maps示例。)
const _ = require("lodash");
const { compose, withProps, lifecycle } = require("recompose");
const {
withScriptjs,
withGoogleMap,
GoogleMap,
Marker,
} = require("react-google-maps");
const { SearchBox } = require("react-google-maps/lib/components/places/SearchBox");
const MapWithASearchBox = compose(
withProps({
googleMapURL: "https://maps.googleapis.com/maps/api/js?key=AIzaSyC4R6AN7SmujjPUIGKdyao2Kqitzr1kiRg&v=3.exp&libraries=geometry,drawing,places",
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `400px` }} />,
mapElement: <div style={{ height: `100%` }} />,
}),
lifecycle({
componentWillMount() {
const refs = {}
this.setState({
bounds: null,
center: {
lat: 41.9, lng: -87.624
},
markers: [],
onMapMounted: ref => {
refs.map = ref;
},
onBoundsChanged: () => {
this.setState({
bounds: refs.map.getBounds(),
center: refs.map.getCenter(),
})
},
onSearchBoxMounted: ref => {
refs.searchBox = ref;
},
onPlacesChanged: () => {
const places = refs.searchBox.getPlaces();
const bounds = new google.maps.LatLngBounds();
places.forEach(place => {
if (place.geometry.viewport) {
bounds.union(place.geometry.viewport)
} else {
bounds.extend(place.geometry.location)
}
});
const nextMarkers = places.map(place => ({
position: place.geometry.location,
}));
const nextCenter = _.get(nextMarkers, '0.position', this.state.center);
this.setState({
center: nextCenter,
markers: nextMarkers,
});
// refs.map.fitBounds(bounds);
},
})
},
}),
withScriptjs,
withGoogleMap
)(props =>
<GoogleMap
ref={props.onMapMounted}
defaultZoom={15}
center={props.center}
onBoundsChanged={props.onBoundsChanged}
>
<SearchBox
ref={props.onSearchBoxMounted}
bounds={props.bounds}
controlPosition={google.maps.ControlPosition.TOP_LEFT}
onPlacesChanged={props.onPlacesChanged}
>
<input
type="text"
placeholder="Customized your placeholder"
style={{
boxSizing: `border-box`,
border: `1px solid transparent`,
width: `240px`,
height: `32px`,
marginTop: `27px`,
padding: `0 12px`,
borderRadius: `3px`,
boxShadow: `0 2px 6px rgba(0, 0, 0, 0.3)`,
fontSize: `14px`,
outline: `none`,
textOverflow: `ellipses`,
}}
/>
</SearchBox>
{props.markers.map((marker, index) =>
<Marker key={index} position={marker.position} />
)}
</GoogleMap>
);
<MapWithASearchBox />
我已经试图解决这个问题很多天了,我一直在寻找教程,但我找不到解决方案。我知道我应该使用:
new google.maps.places.PlacesService()
和添加选项:
const center = new google.maps.LatLng(37.422, -122.084068);
const options = {
location: center
radius: '500',
types: ['hotel']
};
在使用REACT-GOOGLE-MAP时,我需要使用with Scriptjs。但我该如何把这一切放在一起呢?
如何使用带有Google Places API的action-google-map在地图上显示来自Google的酒店标记?
解决方案
您可以通过将GoogleMap
的引用传递给new google.maps.places.PlacesService()
来创建服务,然后通过该服务可以使用nearbySearch()
搜索酒店、餐馆等。正如Google Places Nearby Search API docs所说:
附近搜索允许您按关键字或类型搜索指定区域内的地点。
要触发fetchPlaces()
方法,可以使用GoogleMap组件中的onTilesLoaded
道具或componentDidMount()
。在下面的示例中,我还将fetchPlaces
传递给onBoundChanged
,因为我的搜索基于bounds
,所以每次我移动地图时它都可以给我新的地点,请注意:
const bounds = refs.map.getBounds();
const service = new google.maps.places.PlacesService(refs.map.context.__SECRET_MAP_DO_NOT_USE_OR_YOU_WILL_BE_FIRED);
const request = {
bounds: bounds,
type: ['hotel']
};
以下是我使用recompose
的示例:
/*global google*/
import React from "react"
import { compose, withProps, withHandlers, withState } from "recompose"
import { withScriptjs, withGoogleMap, GoogleMap, Marker } from "react-google-maps"
const MyMapComponent = compose(
withProps({
googleMapURL: "https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places",
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `400px` }} />,
mapElement: <div style={{ height: `100%` }} />,
}),
withScriptjs,
withGoogleMap,
withState('places', 'updatePlaces', ''),
withHandlers(() => {
const refs = {
map: undefined,
}
return {
onMapMounted: () => ref => {
refs.map = ref
},
fetchPlaces: ({ updatePlaces }) => {
let places;
const bounds = refs.map.getBounds();
const service = new google.maps.places.PlacesService(refs.map.context.__SECRET_MAP_DO_NOT_USE_OR_YOU_WILL_BE_FIRED);
const request = {
bounds: bounds,
type: ['hotel']
};
service.nearbySearch(request, (results, status) => {
if (status == google.maps.places.PlacesServiceStatus.OK) {
console.log(results);
updatePlaces(results);
}
})
}
}
}),
)((props) => {
return (
<GoogleMap
onTilesLoaded={props.fetchPlaces}
ref={props.onMapMounted}
onBoundsChanged={props.fetchPlaces}
defaultZoom={8}
defaultCenter={{ lat: 51.508530, lng: -0.076132 }}
>
{props.places && props.places.map((place, i) =>
<Marker key={i} position={{ lat: place.geometry.location.lat(), lng: place.geometry.location.lng() }} />
)}
</GoogleMap>
)
})
export default class MyFancyComponent extends React.PureComponent {
render() {
return (
<MyMapComponent />
)
}
}
相关文章