Reactjs - 谷歌地图 - 样式InfoWindow

时间:2016-07-05 12:01:24

标签: javascript google-maps-api-3 reactjs

我正在尝试在

中更改InfoWindow的样式

这是我使用的代码:

<InfoWindow options={{maxWidth: 900}} position={self.state.position} ref="infoWindow" onCloseclick={self.onLineWindowClose}>
    <div className="berlin" style={{height: '120px',width: '260px', fontFamily: 'Roboto'}}>
        <div style={{height: '20px'}}>
            <div style={{float: 'left', padding: '3px 0 0 6px'}}>From: </div>
            <div style={{float: 'left', padding: "3px", color: '#3497d9'}}>{self.state.startLocation.City}</div>
        </div>
        <div style={{height: '20px', clear: 'both'}}>
            <div style={{float: 'left', padding: '3px 0 0 6px'}}>To: </div>
            <div style={{float: 'left', padding: "3px", color: '#3497d9'}}>{self.state.endLocation.City}</div>
        </div>
        <LineList relationInfo={this.state.relationDetails} />
    </div>
</InfoWindow>

问题很简单。我该如何改变它的外观?我尝试设置className。我也尝试将选项传递给它。但似乎没有任何效果。

2 个答案:

答案 0 :(得分:2)

对于使用InfoBox且造型有问题的任何人,以下内容对我有用:

<强> JS

<InfoBox key={i}
    defaultPosition={new google.maps.LatLng(marker.lat, marker.lng)}
    options={{
        pane: "overlayLayer",
        pixelOffset: new google.maps.Size(-140, -60),
        alignBottom: true,
        boxStyle: {
            boxShadow: `3px 3px 10px rgba(0,0,0,0.6)`
        },
        closeBoxURL : ""
    }}
>
    <div className="google_map_infobox">
        {marker.txt}
    </div>
</InfoBox>

<强> CSS

.google_map_infobox
{
    background: #fff;
    padding: 1em;
    text-align: center;
    font-size: 1.1rem;
    box-shadow: 3px 3px 10px rgba(0,0,0,0.6);
    border: 1px solid #666;
}

这会创建一个框,该框位于标记的中心,并且有一个框阴影,没有关闭按钮等。boxStyle选项是我在谷歌搜索中偶然发现的。

我还使用CSS做了一些盒子样式。也许我可以在boxStyle属性中完成所有操作,但我宁愿在CSS中保留尽可能多的内容。 box-shadow是唯一不能通过CSS工作的东西。

希望这可以帮助使用react-google-maps的人。

答案 1 :(得分:1)

我建议您为谷歌地图创建自己的组件,并使用&#34; plain&#34;创建自定义信息窗口。 JavaScript的。通过这种方式,您可以直接使用所有谷歌地图&#34; native&#34;属性等,并且不需要使用任何超级复杂和有限的组件库:))

示例google maps wrapper for react(只是简单示例):

&#13;
&#13;
import React, { Component, PropTypes } from 'react';

class GoogleMap extends Component {

  componentDidMount() {
    this.map = new google.maps.Map(this.refs.map, {
      scrollwheel: true,
      zoom: 13,
      draggable: true,
      mapTypeControl: false,
      streetViewControl: false,
      zoomControlOptions: {
        position: google.maps.ControlPosition.TOP_LEFT,
        style: google.maps.ZoomControlStyle.LARGE,
      },
      center: new google.maps.LatLng(60.16985569999999, 24.938379),
    });

    this.props.onGetMap(this.map);
  }

  render() {
    const mapStyle = {
      height: '100%',
      width: '100%',
    };

    return (
      <div ref="map" style={mapStyle}></div>
    );
  }
}

GoogleMap.propTypes = {
  onGetMap: PropTypes.func.isRequired,
};

export default GoogleMap;
&#13;
&#13;
&#13;

然后你就可以使用它:

&#13;
&#13;
import React, { Component, PropTypes } from 'react';
import GoogleMap from 'components/GoogleMap';

class Some extends Component {

  constructor(props, context) {
    super(props, context);
    this.onMapReady = this.onMapReady.bind(this);
    this.state = {
      map: null,
      markers: [],
    };
  }

  onMapReady(map) {
    this.setState({
      map,
    });
    // Here add some markers etc..
  }

  render() {
    return (
      <div className="some">
        <GoogleMap onGetMap={this.onMapReady} />
      </div>
    );
  }
}

export default Some;
&#13;
&#13;
&#13;

示例信息窗口:

&#13;
&#13;
class BubbleOverlay extends google.maps.OverlayView {

  constructor(options) {
    // Initialize all properties.
    super(options);
    this.options = {};

    this.options.map = options.map;
    this.options.location = options.location;
    this.options.borderColor = options.borderColor || '#666666';
    this.options.borderWidth = options.borderWidth || 1;
    this.options.backgroundColor = options.backgroundColor || '#fff';
    this.options.arrowSize = options.arrowSize || 15;
    this.options.contentHeight = options.contentHeight || 200;
    this.options.contentWidth = options.contentWidth || 200;
    this.options.zIndex = options.zIndex || 1000;
    this.options.onClose = options.onClose;
    // Explicitly call setMap on this overlay.
    this.setMap(options.map);
  }

  /**
   * Convert number to pixels
   * @param  {number} num Number to convert
   * @return {string}     Number in pixels
   */
  px(num) {
    if (num) {
      // 0 doesn't need to be wrapped
      return `${num}px`;
    }
    return num;
  }

/**
 * onAdd is called when the map's panes are ready and the overlay has been
 * added to the map.
 */
  onAdd() {
    if (!this.bubble) {
      this.createDOMElements();
    }

    // Add the element to the "overlayLayer" pane.
    const panes = this.getPanes();
    if (panes) {
      panes.overlayMouseTarget.appendChild(this.bubble);
    }
  }

  createContent() {
    const content = document.createElement('div');
    content.style.borderStyle = 'solid';
    content.style.borderWidth = '1px';
    content.style.borderColor = this.options.borderColor;
    content.style.backgroundColor = this.options.backgroundColor;
    content.style.zIndex = this.options.zIndex;
    content.style.width = this.px(this.options.contentWidth);
    content.style.height = this.px(this.options.contentHeight);
    content.style.position = 'relative';
    content.className = 'bubble-overlay-content';

    return content;
  }

  createCloseBtn() {
    const btn = document.createElement('div');
    btn.className = 'bubble-overlay-btn-close';

    const iconClose = document.createElement('span');
    iconClose.className = 'glyphicon glyphicon-remove';
    btn.appendChild(iconClose);

    return btn;
  }

  createArrow() {
    const arrowSize = this.options.arrowSize;
    const borderWidth = this.options.borderWidth;
    const borderColor = this.options.borderColor;
    const backgroundColor = this.options.backgroundColor;


    const arrowOuterSizePx = this.px(arrowSize);
    const arrowInnerSizePx = this.px(Math.max(0, arrowSize - borderWidth));

    const arrow = document.createElement('div');
    arrow.style.position = 'relative';
    arrow.style.marginTop = this.px(-borderWidth);

    const arrowInner = document.createElement('div');
    const arrowOuter = document.createElement('div');

    arrowOuter.style.position = arrowInner.style.position = 'absolute';
    arrowOuter.style.left = arrowInner.style.left = '50%';
    arrowOuter.style.height = arrowInner.style.height = '0';
    arrowOuter.style.width = arrowInner.style.width = '0';
    arrowOuter.style.marginLeft = this.px(-arrowSize);
    arrowOuter.style.borderWidth = arrowOuterSizePx;
    arrowOuter.style.borderStyle = arrowInner.style.borderStyle = 'solid';
    arrowOuter.style.borderBottomWidth = 0;
    arrowOuter.style.display = '';

    arrowOuter.style.borderColor = `${borderColor} transparent transparent`;
    arrowInner.style.borderColor = `${backgroundColor} transparent transparent`;

    arrowOuter.style.zIndex = this.options.zIndex + 1;
    arrowInner.style.zIndex = this.options.zIndex + 1;

    arrowOuter.style.borderTopWidth = arrowOuterSizePx;
    arrowInner.style.borderTopWidth = arrowInnerSizePx;

    arrowOuter.style.borderLeftWidth = arrowOuterSizePx;
    arrowInner.style.borderLeftWidth = arrowInnerSizePx;

    arrowOuter.style.borderRightWidth = arrowOuterSizePx;
    arrowInner.style.borderRightWidth = arrowInnerSizePx;

    arrowOuter.style.marginLeft = this.px(-(arrowSize));
    arrowInner.style.marginLeft = this.px(-(arrowSize - borderWidth));

    arrow.appendChild(arrowOuter);
    arrow.appendChild(arrowInner);

    return arrow;
  }

/**
 * Create dom elements
 */
  createDOMElements() {
    const bubble = this.bubble = document.createElement('div');
    bubble.style.position = 'absolute';
    bubble.style.zIndex = this.options.zIndex - 1;
    bubble.style.boxShadow = '0px 0px 15px rgba(0,0,0,0.4)';

    const content = this.content = this.createContent();
    const arrow = this.arrow = this.createArrow();
    const closeBtn = this.closeBtn = this.createCloseBtn();

    closeBtn.style.zIndex = this.options.zIndex + 1000;
    closeBtn.onclick = this.options.onClose;
    bubble.appendChild(content);
    bubble.appendChild(arrow);
    bubble.appendChild(closeBtn);
  }


  /* Pan the map to fit the InfoBox.
   */
  panMap() {
    // if we go beyond map, pan map
    const map = this.options.map;
    const bounds = map.getBounds();
    if (!bounds) return;

    // The position of the infowindow
    const position = this.options.location;

    // The dimension of the infowindow
    const iwWidth = this.options.contentWidth;
    const iwHeight = this.options.contentHeight;

    // The offset position of the infowindow
    const iwOffsetX = Math.round(this.options.contentWidth / 2);
    const iwOffsetY = Math.round(this.options.contentHeight + this.options.arrowSize + 10);

    // Padding on the infowindow
    const padX = 40;
    const padY = 40;

    // The degrees per pixel
    const mapDiv = map.getDiv();
    const mapWidth = mapDiv.offsetWidth;
    const mapHeight = mapDiv.offsetHeight;
    const boundsSpan = bounds.toSpan();
    const longSpan = boundsSpan.lng();
    const latSpan = boundsSpan.lat();
    const degPixelX = longSpan / mapWidth;
    const degPixelY = latSpan / mapHeight;

    // The bounds of the map
    const mapWestLng = bounds.getSouthWest().lng();
    const mapEastLng = bounds.getNorthEast().lng();
    const mapNorthLat = bounds.getNorthEast().lat();
    const mapSouthLat = bounds.getSouthWest().lat();

    // The bounds of the infowindow
    const iwWestLng = position.lng() + (iwOffsetX - padX) * degPixelX;
    const iwEastLng = position.lng() + (iwOffsetX + iwWidth + padX) * degPixelX;
    const iwNorthLat = position.lat() - (iwOffsetY - padY) * degPixelY;
    const iwSouthLat = position.lat() - (iwOffsetY + iwHeight + padY) * degPixelY;

    // calculate center shift
    const shiftLng =
        (iwWestLng < mapWestLng ? mapWestLng - iwWestLng : 0) +
        (iwEastLng > mapEastLng ? mapEastLng - iwEastLng : 0);
    const shiftLat =
        (iwNorthLat > mapNorthLat ? mapNorthLat - iwNorthLat : 0) +
        (iwSouthLat < mapSouthLat ? mapSouthLat - iwSouthLat : 0);

    // The center of the map
    const center = map.getCenter();

    // The new map center
    const centerX = center.lng() - shiftLng;
    const centerY = center.lat() - shiftLat;

    // center the map to the new shifted center
    map.setCenter(new google.maps.LatLng(centerY, centerX));
  }

  draw() {
    // Resize the image's div to fit the indicated dimensions.
    const bubble = this.bubble;

    // Position the overlay
    const point = this.getProjection().fromLatLngToDivPixel(this.options.location);

    if (point) {
      bubble.style.left = this.px(point.x - Math.round(this.options.contentWidth / 2));
      bubble.style.top = this.px(point.y - Math.round(this.options.contentHeight + this.options.arrowSize + 10));
    }
  }

  // The onRemove() method will be called automatically from the API if
  // we ever set the overlay's map property to 'null'.
  onRemove() {
    this.bubble.parentNode.removeChild(this.bubble);
    this.bubble = null;
  }
}

export default BubbleOverlay;
&#13;
&#13;
&#13;