简体   繁体   English

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

[英]How to change the opacity of a GroundOverlay in react-google-maps?

Using the react-google-maps example with the GroundOverlay component as an example (cf. https://github.com/khpeek/beomaps/blob/master/src/App.js ), I'd like to make a slider which changes the opacity of the overlay.使用带有GroundOverlay组件的react-google-maps示例(参见https://github.com/khpeek/beomaps/blob/master/src/App.js ),我想制作一个滑块更改叠加层的不透明度。

For example, currently, if I render this component, I get an overlay with a fixed opacity of 0.5 :例如,目前,如果我渲染这个组件,我会得到一个固定不透明度为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>
);

which looks like this:看起来像这样:

在此处输入图片说明

I'm struggling to see, however, how to change the opacity 'dynamically' with a slider.但是,我很难看到如何使用滑块“动态”更改不透明度。 Ultimately, I believe I would have to call the setOpacity method on the instance of the google.maps.GroundOverlay class (cf. https://developers.google.com/maps/documentation/javascript/reference/image-overlay#GroundOverlay ).最终,我相信我必须在google.maps.GroundOverlay类的实例上调用setOpacity方法(参见https://developers.google.com/maps/documentation/javascript/reference/image-overlay#GroundOverlay ) . However, if I look at the source code for the <GroundOverlay> component (cf. https://github.com/tomchentw/react-google-maps/blob/ca5c5c6f5346fb3ee0037893fbca488a408c9938/lib/components/GroundOverlay.js#L59 ),但是,如果我查看<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
)) /*

then it seems like it has only a getOpacity() method, but no setOpacity() one.那么它似乎只有一个getOpacity()方法,但没有setOpacity()方法。 Also, the groundOverlay variable is a local variable of the function GroundOverlay(props, context) , so I don't see how I could access its setOpacity method.此外, groundOverlay变量是function GroundOverlay(props, context)的局部变量,所以我不知道如何访问它的setOpacity方法。

Any ideas on how to approach this?关于如何解决这个问题的任何想法?

Update更新

I've noticed that the GroundOverlay component accepts an opacity prop which determines its opacity.我注意到GroundOverlay组件接受一个决定其不透明度的opacity道具。 Using this, I tried to create a component AdjustableGroundoverlay containing both a <GroundOverlay> and a <button> (for now) to change the GroundOverlay 's opacity:使用这个,我尝试创建一个包含<GroundOverlay>和一个<button> (现在)的组件AdjustableGroundoverlay来改变GroundOverlay的不透明度:

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>
    );
  }
}

However, I've noticed that when I click the button, although its label changes from Opacity: 0.5 to Opacity: 1 , the actual opacity of the overlay doesn't change:但是,我注意到当我单击按钮时,尽管它的标签从Opacity: 0.5更改为Opacity: 1 ,但叠加层的实际不透明度并没有改变:

在此处输入图片说明

As I understand from https://reactjs.org/docs/handling-events.html , calling setState() on the AdjustableGroundoverlay should cause it to call its render() method again, thereby passing the new this.state.opacity as a prop to GroundOverlay and changing its opacity.正如我从https://reactjs.org/docs/handling-events.html了解到的,在AdjustableGroundoverlay上调用setState()应该会导致它再次调用它的render()方法,从而将新的this.state.opacity作为支持GroundOverlay并更改其不透明度。 I don't understand why this is not working?我不明白为什么这不起作用?

In react-google-maps library default properties (eg defaultOpacity )are immutable after the component is instantiated, so in order GroundOverlay component to reflect the changes, opacity needs to be utilized instead.react-google-maps库中, default属性(例如defaultOpacity )在组件实例化后是不可变的,因此为了让GroundOverlay组件反映更改,需要使用opacity来代替。

Now comes the turn of changes, instead of accessing underlying google.maps.GroundOverlay object , i would suggest a React way via state .现在轮到更改,而不是访问底层google.maps.GroundOverlay对象,我建议通过state使用React 方式 Since in your example recompose library is utilized opacity state could be introduced and a handler to change its value could look like this:由于在您的示例中使用了recompose库,因此可以引入opacity状态,并且更改其值的处理程序可能如下所示:

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

For details about withStateHandlers refer official documentation有关withStateHandlers详细信息,请参阅官方文档

Here is an example to reflect the change of opacity 'dynamically' ( for demonstration purposes button is used instead of slider ):这是一个“动态”反映不透明度变化的示例(出于演示目的,使用按钮而不是滑块):

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这是一个演示

Instead of using withStateHandlers as in the answer above, I ended up just changing the defaultOpacity prop to opacity in the MapWithGroundOverlay component:withStateHandlers像上面的答案那样使用withStateHandlers ,而是将MapWithGroundOverlay组件中的defaultOpacity MapWithGroundOverlay更改为opacity

/* 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>
);

Now, using the AjustableGroundoverlay component posted in the update above, the opacity changes when the button is clicked:现在,使用上面更新中发布的AjustableGroundoverlay组件,单击按钮时不透明度会发生变化:

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM