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


看起来像这样:

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

但是,我正在努力查看如何使用滑块“动态”更改不透明度。最终,我相信我将不得不在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)的局部变量,因此我看不到如何访问其setOpacity方法。

关于如何解决这个问题的任何想法?

更新资料

我注意到GroundOverlay组件接受确定其不透明度的opacity道具。使用此方法,我尝试创建同时包含AdjustableGroundoverlay<GroundOverlay>的组件<button>来更改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>
    );
  }
}


但是,我注意到,当我单击按钮时,尽管其标签从Opacity: 0.5更改为Opacity: 1,但是叠加层的实际不透明度并没有改变:

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

据我从https://reactjs.org/docs/handling-events.html理解,在setState()上调用AdjustableGroundoverlay应该使它再次调用其render()方法,从而将新的this.state.opacity作为道具传递给GroundOverlay并更改其不透明度。我不明白为什么这行不通?

最佳答案

react-google-maps库中,实例化组件后,default属性(例如defaultOpacity)是不变的,因此为了使GroundOverlay组件反映更改,需要使用opacity代替。

现在轮到更改了,而不是访问基础google.maps.GroundOverlay object,我建议通过React way来使用state。因为在您的示例中使用了recompose library,所以可以引入opacity状态,并且可以更改其值的处理程序如下所示:

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

关于javascript - 如何更改react-google-maps中GroundOverlay的不透明度?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55980161/

10-09 14:50