代码之家  ›  专栏  ›  技术社区  ›  Kurt Peek

如何在react google maps中更改GroundOverlay的不透明度?

  •  0
  • Kurt Peek  · 技术社区  · 6 年前

    使用 react-google-maps GroundOverlay 以组件为例(参见。 https://github.com/khpeek/beomaps/blob/master/src/App.js ),我想制作一个滑块来更改覆盖的不透明度。

    0.5 :

    /* global google */
    
    import React from "react"
    import { compose } from "recompose"
    import { 
      withScriptjs,
      withGoogleMap,
      GoogleMap,
      GroundOverlay } from "react-google-maps"
    
    export const MapWithGroundOverlay = compose(
      withScriptjs,
      withGoogleMap
    )(props =>
      <GoogleMap
        defaultZoom={12}
        defaultCenter={{lat: 40.740, lng: -74.18}}
      >
        <GroundOverlay
          defaultUrl="https://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg"
          defaultBounds={new google.maps.LatLngBounds(
            new google.maps.LatLng(40.712216, -74.22655),
            new google.maps.LatLng(40.773941, -74.12544)
          )}
          defaultOpacity={.5}
        />
      </GoogleMap>
    );
    

    看起来是这样的:

    enter image description here

    不过,我很难看到如何用滑块“动态”改变不透明度。最后,我相信我会打电话给 setOpacity 方法的实例 google.maps.GroundOverlay 等级(参见。 https://developers.google.com/maps/documentation/javascript/reference/image-overlay#GroundOverlay <GroundOverlay> 组件(参见。 https://github.com/tomchentw/react-google-maps/blob/ca5c5c6f5346fb3ee0037893fbca488a408c9938/lib/components/GroundOverlay.js#L59 ),

    var GroundOverlay = (exports.GroundOverlay = (function(_React$PureComponent) {
      ;(0, _inherits3.default)(GroundOverlay, _React$PureComponent)
    
      /*
       * @see https://developers.google.com/maps/documentation/javascript/3.exp/reference#GroundOverlay
       */
      function GroundOverlay(props, context) {
        ;(0, _classCallCheck3.default)(this, GroundOverlay)
    
        var _this = (0, _possibleConstructorReturn3.default)(
          this,
          (
            GroundOverlay.__proto__ || (0, _getPrototypeOf2.default)(GroundOverlay)
          ).call(this, props, context)
        )
    
        ;(0, _warning2.default)(
          !props.url || !props.bounds,
          "\nFor GroundOveray, url and bounds are passed in to constructor and are immutable\n after iinstantiated. This is the behavior of Google Maps JavaScript API v3 (\n See https://developers.google.com/maps/documentation/javascript/reference#GroundOverlay)\n Hence, use the corresponding two props provided by `react-google-maps`.\n They're prefixed with _default_ (defaultUrl, defaultBounds).\n\n In some cases, you'll need the GroundOverlay component to reflect the changes\n of url and bounds. You can leverage the React's key property to remount the\n component. Typically, just `key={url}` would serve your need.\n See https://github.com/tomchentw/react-google-maps/issues/655\n"
        )
        var groundOverlay = new google.maps.GroundOverlay(
          props.defaultUrl || props.url,
          props.defaultBounds || props.bounds
        )
        ;(0, _MapChildHelper.construct)(
          GroundOverlay.propTypes,
          updaterMap,
          _this.props,
          groundOverlay
        )
        groundOverlay.setMap(_this.context[_constants.MAP])
        _this.state = (0, _defineProperty3.default)(
          {},
          _constants.GROUND_LAYER,
          groundOverlay
        )
        return _this
      }
    
      ;(0, _createClass3.default)(GroundOverlay, [
        {
          key: "componentDidMount",
          value: function componentDidMount() {
            ;(0, _MapChildHelper.componentDidMount)(
              this,
              this.state[_constants.GROUND_LAYER],
              eventMap
            )
          },
        },
        {
          key: "componentDidUpdate",
          value: function componentDidUpdate(prevProps) {
            ;(0, _MapChildHelper.componentDidUpdate)(
              this,
              this.state[_constants.GROUND_LAYER],
              eventMap,
              updaterMap,
              prevProps
            )
          },
        },
        {
          key: "componentWillUnmount",
          value: function componentWillUnmount() {
            ;(0, _MapChildHelper.componentWillUnmount)(this)
            var GroundOverlay = this.state[_constants.GROUND_LAYER]
            if (GroundOverlay) {
              GroundOverlay.setMap(null)
            }
          },
        },
        {
          key: "render",
          value: function render() {
            return false
          },
    
          /**
           * Gets the `LatLngBounds` of this overlay.
           * @type LatLngBoundsLatLngBounds
           * @public
           */
        },
        {
          key: "getBounds",
          value: function getBounds() {
            return this.state[_constants.GROUND_LAYER].getBounds()
          },
    
          /**
           * Returns the opacity of this ground overlay.
           * @type number
           * @public
           */
        },
        {
          key: "getOpacity",
          value: function getOpacity() {
            return this.state[_constants.GROUND_LAYER].getOpacity()
          },
    
          /**
           * Gets the url of the projected image.
           * @type string
           * @public
           */
        },
        {
          key: "getUrl",
          value: function getUrl() {
            return this.state[_constants.GROUND_LAYER].getUrl()
          },
        },
      ])
      return GroundOverlay
    })(
      _react2.default.PureComponent
    )) /*
    

    getOpacity() 方法,但不是 setOpacity() 一个。而且 groundOverlay 变量是 function GroundOverlay(props, context) ,所以我不知道如何才能访问它 方法。

    有什么办法吗?

    更新

    我注意到 叠加层 opacity 决定其不透明度的道具。使用这个,我试图创建一个组件 AdjustableGroundoverlay 包含两个 < 以及 <button> (暂时)改变 叠加层

    import React from "react"
    import { MapWithGroundOverlay } from "./MapWithGroundOverlay"
    
    export class AdjustableGroundoverlay extends React.PureComponent {
      constructor(props, context) {
        super(props, context)
        this.state = {opacity: 0.5}
        this.handleClick = this.handleClick.bind(this);
      }
    
      handleClick() {
        this.setState(state => ({
          opacity: 1.0
        }));
      }
    
      render() {
        return (
          <div>
            <MapWithGroundOverlay
              googleMapURL={`https://maps.googleapis.com/maps/api/js?key=${process.env.REACT_APP_GOOGLE_MAPS_API_KEY}&v=3.exp&libraries=geometry,drawing,places`}
              loadingElement={<div style={{ height: `100%` }} />}
              containerElement={<div style={{ height: `600px` }} />}
              mapElement={<div style={{ height: `100%` }} />}
              opacity={this.state.opacity}
            />
            <button onClick={this.handleClick}>
              {`Opacity: ${this.state.opacity}`}
            </button>
          </div>
        );
      }
    }
    

    但是,我注意到当我单击按钮时,尽管它的标签从 Opacity: 0.5 Opacity: 1 ,覆盖的实际不透明度不会更改:

    enter image description here

    据我所知 https://reactjs.org/docs/handling-events.html ,呼叫 setState() 可调接地覆盖层 render() 方法,从而传递新的 this.state.opacity 作为支柱 叠加层 改变它的不透明度。我不明白为什么这不管用?

    0 回复  |  直到 6 年前
        1
  •  1
  •   Vadim Gremyachev    6 年前

    react-google-maps 图书馆 default defaultOpacity )在组件被实例化之后是不可变的,所以 GroundOverlay 组件以反映更改, opacity 需要加以利用。

    google.maps.GroundOverlay object ,我建议 React way 通过 state recompose library 被利用 不透明度 可以引入状态,更改其值的处理程序可以如下所示:

    withStateHandlers(
        () => ({
          opacity: 0.1
        }),
        {
          incrementOpacity: ({ opacity }) => () => ({
            opacity: opacity >= 1.0 ? 0.0 : opacity + 0.1
          })
        }
    )
    

    有关的详细信息 withStateHandlers 参考 official documentation

    为了演示,使用按钮而不是滑块 ):

    export const MapWithGroundOverlay = compose(
      withScriptjs,
      withGoogleMap,
      withStateHandlers(
        () => ({
          opacity: 0.1
        }),
        {
          incrementOpacity: ({ opacity }) => () => ({
            opacity: opacity >= 1.0 ? 0.0 : opacity + 0.1
          })
        }
      )
    )(props => (
      <div>
        <button onClick={props.incrementOpacity}>Increment opacity</button>
        <GoogleMap defaultZoom={12} defaultCenter={{ lat: 40.74, lng: -74.18 }}>
          <GroundOverlay
            defaultUrl="https://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg"
            defaultBounds={
              new google.maps.LatLngBounds(
                new google.maps.LatLng(40.712216, -74.22655),
                new google.maps.LatLng(40.773941, -74.12544)
              )
            }
            defaultOpacity={props.opacity}
          />
        </GoogleMap>
      </div>
    ));
    

    Here is a demo

        2
  •  0
  •   Kurt Peek    6 年前

    而不是使用 withStateHandlers 在上面的答案中,我最后只是改变了 defaultOpacity 支持 opacity MapWithGroundOverlay 组成部分:

    /* global google */
    
    import React from "react"
    import { compose } from "recompose"
    import {
      withScriptjs,
      withGoogleMap,
      GoogleMap,
      GroundOverlay } from "react-google-maps"
    
    export const MapWithGroundOverlay = compose(
      withScriptjs,
      withGoogleMap
    )(props =>
      <GoogleMap
        defaultZoom={12}
        defaultCenter={{lat: 40.740, lng: -74.18}}
      >
        <GroundOverlay
          defaultUrl="https://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg"
          defaultBounds={new google.maps.LatLngBounds(
            new google.maps.LatLng(40.712216, -74.22655),
            new google.maps.LatLng(40.773941, -74.12544)
          )}
          opacity={props.opacity}
        />
      </GoogleMap>
    );
    

    AjustableGroundoverlay 组件发布在上面的更新中,单击按钮时不透明度会更改:

    enter image description here