我正在构建一个类似 Zillow 的地图,页面正文中带有房地产属性点,页面标题中有过滤器。
我需要的是将地图居中并缩放react-google-maps
从外部谷歌地点过滤器中选择谷歌地点。目前,我可以将地图居中选择位置,但不能放大(那是因为我需要在每次放大/缩小时重新获取数据,因此需要控制缩放,请参阅下面的代码(。
我尝试从这里使用fitBounds
,但我的代码ref
总是undefined
.
我有 API 根据过滤器获取点,参数如下:
viewPort: {
northEast: { lat: 57.04834755670983, lng: 24.3255340332031 },
southWest: { lat: 56.83635114109457, lng: 23.93826596679685 }
},
priceMin: 0,
priceMax: 500,
propType: "RENT",
numRooms: 3,
...
在标题部分,还有地址过滤器输入,具有Google自动完成功能。选中后,Google 会提供有关地点的信息:
"geometry" : {
...
"viewport" : {
"northeast" : {
"lat" : 56.95662478029149,
"lng" : 24.2054917802915
},
"southwest" : {
"lat" : 56.9539268197085,
"lng" : 24.2027938197085
}
}
...
这是我Map
组件:
import React, { Component } from 'react';
import { compose, withProps, withState, withHandlers } from "recompose";
import {
withGoogleMap,
GoogleMap,
Marker,
} from "react-google-maps";
import { MarkerClusterer } from "react-google-maps/lib/components/addons/MarkerClusterer";
const defaultMapOptions = {
fullscreenControl: false,
streetViewControl: false,
};
const PropertyMap = compose(
withProps({
loadingElement: <div>Loading...</div>,
containerElement: <div style={{ height: "500px" }} />,
mapElement: <div style={{ height: `100%` }} />,
}),
withState('zoom', 'onZoomChange', 11),
withHandlers(() => {
const refs = {
map: undefined,
}
return {
onMapMounted: () => ref => {
refs.map = ref
},
onZoomChanged: ({ onZoomChange, onMapBoundsChange }) => () => {
onZoomChange(refs.map.getZoom())
onMapBoundsChange(refs.map.getBounds());
},
onDragEnd: ({ onMapBoundsChange }) => () => {
onMapBoundsChange(refs.map.getBounds());
},
onMarkerClustererClick: () => (markerClusterer) => {
const clickedMarkers = markerClusterer.getMarkers()
console.log(`Current clicked markers length: ${clickedMarkers.length}`)
console.log(clickedMarkers)
}
}
}),
withGoogleMap
)(props =>
<GoogleMap
defaultCenter={props.defaultCenter ? props.defaultCenter : { lat: 56.9425, lng: 24.1319 }}
zoom={props.zoom}
ref={props.onMapMounted}
onZoomChanged={props.onZoomChanged}
onDragEnd={props.onDragEnd}
defaultOptions={defaultMapOptions}
>
<MarkerClusterer
onClick={props.onMarkerClustererClick}
averageCenter
enableRetinaIcons
gridSize={60}
key={props.mapUid}
>
{props.features !== null && props.features.map(feature => {
const coord = { lng: feature.geometry.coordinates[0], lat: feature.geometry.coordinates[1] };
return <Marker key={feature.id} position={coord} />;
})}
</MarkerClusterer>
</GoogleMap>
);
export default PropertyMap;
所以我想我想让在道具中传递zoom
参数成为可能,就像这样:
<PropertyMap
mapUid={this.state.mapUid}
features={this.state.features}
key={this.state.defaultCenter ? `${this.state.defaultCenter.lat}` : '1'}
defaultCenter={this.state.defaultCenter}
defaultZoom={calculateZoomFromViewPort(this.state.viewPort)}
onMapBoundsChange={this.handleMapBoundsChange}
/>
这样我就可以calculateZoomFromViewPort(this.state.viewPort)
,但是我需要以某种方式将其设置为默认值withState
zoom
。
所以我需要的是一些如何将默认缩放值传递给withState('zoom', 'onZoomChange', 11)
,(11
目前是硬编码的(。但是我是recompose
包的新手,但它是否在react-google-maps
包示例中大量使用。
如果您有其他想法,如何根据 Google Place 的viewport
和center
参数缩放和居中地图,请分享!
fitbounds()
是实现自动缩放的推荐方法。请记住,引用始终是在组件首次渲染后创建的。我已经通过添加 fitBounds 对您的代码进行了更改。可能很少有语法错误,因为我更喜欢使用像基于类的实用程序包装器这样的反应谷歌地图。使用 redux 和组件生命周期更容易管理。以下是最新的代码:
import React, { Component } from 'react';
import { compose, withProps, withState, withHandlers } from "recompose";
import {
withGoogleMap,
GoogleMap,
Marker,
} from "react-google-maps";
import { MarkerClusterer } from "react-google-maps/lib/components/addons/MarkerClusterer";
const defaultMapOptions = {
fullscreenControl: false,
streetViewControl: false,
};
const PropertyMap = compose(
withProps({
loadingElement: <div>Loading...</div>,
containerElement: <div style={{ height: "500px" }} />,
mapElement: <div style={{ height: `100%` }} />,
}),
withState('zoom', 'onZoomChange', 11),
withHandlers(() => {
const refs = {
map: undefined,
}
return {
onMarkersUpdate: ()=> () => {
if(refs.map){
const mapBounds = new google.maps.LatLngBounds();
//just add markers position into mapBounds
markers.forEach((marker)=>{
mapBounds.extend(marker.position)
});
this.refs.map.fitBounds(mapBbounds);
}
},
onZoomChanged: ({ onZoomChange, onMapBoundsChange }) => () => {
onZoomChange(refs.map.getZoom())
onMapBoundsChange(refs.map.getBounds());
},
onDragEnd: ({ onMapBoundsChange }) => () => {
onMapBoundsChange(refs.map.getBounds());
},
onMarkerClustererClick: () => (markerClusterer) => {
const clickedMarkers = markerClusterer.getMarkers()
console.log(`Current clicked markers length: ${clickedMarkers.length}`)
console.log(clickedMarkers)
}
}
}),
withGoogleMap
)(props =>
<GoogleMap
defaultCenter={props.defaultCenter ? props.defaultCenter : { lat: 56.9425, lng: 24.1319 }}
zoom={props.zoom}
ref='map'
onZoomChanged={props.onZoomChanged}
onDragEnd={props.onDragEnd}
defaultOptions={defaultMapOptions}
>
{props.onMarkersUpdate()}
<MarkerClusterer
onClick={props.onMarkerClustererClick}
averageCenter
enableRetinaIcons
gridSize={60}
key={props.mapUid}
>
{props.features !== null && props.features.map(feature => {
const coord = { lng: feature.geometry.coordinates[0], lat: feature.geometry.coordinates[1] };
return <Marker key={feature.id} position={coord} />;
})}
</MarkerClusterer>
</GoogleMap>
);
export default PropertyMap;
请随时对我做出反应。如果您为此制作代码沙箱。修复语法错误会更容易。不要错过fitbounds()
.它让我们的事情变得更容易。