【问题标题】:Center AND zoom by prop in react-google-maps?在 react-google-maps 中按道具居中和缩放?
【发布时间】:2019-01-20 09:07:08
【问题描述】:

我正在构建一个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),但是我需要以某种方式将其设置为withStatezoom默认值。

所以我需要一些如何将默认缩放值传递给withState('zoom', 'onZoomChange', 11),(11 目前是硬编码的)。但我是 recompose 包的新手,但它在 react-google-maps 包示例中大量使用。

如果您有其他想法,如何根据来自 Google place 的 viewportcenter 参数缩放和居中地图,请分享!

【问题讨论】:

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


    【解决方案1】:

    fitbounds() 是实现自动缩放的推荐方式。记住 refs 总是在组件第一次渲染后创建。我通过添加 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;
    

    请随时对我做出反应。如果您为此制作一个代码框。修复语法错误会更容易。不要错过fitbounds()。它使我们的工作变得更轻松。

    【讨论】:

      猜你喜欢
      • 2022-12-03
      • 2019-01-09
      • 2013-12-26
      • 1970-01-01
      • 2019-12-26
      • 2015-07-10
      • 2021-09-27
      • 1970-01-01
      • 2012-11-16
      相关资源
      最近更新 更多