在react-google-maps中居中并通过prop缩放吗?

时间:2018-08-13 15:21:34

标签: reactjs google-maps google-places-api react-google-maps recompose

我正在建立一个Zillow-like地图,在页面正文中包含房地产属性点,并在页面标题中使用过滤器。

从外部Google地方信息过滤器中选择Google地方信息时,我需要居中并缩放react-google-maps地图。目前,我能够将地图集中在位置选择上,但无法放大(这是因为我需要在每次放大/缩小时都重新获取数据,因此需要控制缩放,请参见下面的代码)。

我尝试使用here中的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地方的viewportcenter参数对地图进行缩放和居中,请分享!

1 个答案:

答案 0 :(得分:0)

fitbounds()是实现自动缩放的推荐方法。请记住,始终在首次渲染组件后创建引用。我已经通过添加fitBounds对您的代码进行了更改。由于我更喜欢​​使用react-google-maps(例如基于类的实用程序包装器),因此语法可能很少出现错误。使用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;

请随时对我做出反应。如果为此创建一个codeandbox。解决语法错误会更容易。而且不要错过fitbounds()。它使我们更轻松。