Reactjs - 谷歌地图 - 样式信息窗口
Posted
技术标签:
【中文标题】Reactjs - 谷歌地图 - 样式信息窗口【英文标题】:Reactjs - google maps - Style InfoWindow 【发布时间】:2016-11-07 06:17:33 【问题描述】:我正在尝试在
中更改 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>
问题很简单。如何更改其外观?我尝试设置类名。我也尝试将选项传递给它。但似乎没有任何效果。
【问题讨论】:
【参考方案1】:我建议为谷歌地图创建自己的组件并使用“普通”javascript 创建自定义信息窗口。这样你就可以直接使用所有谷歌地图的“原生”属性等,而不需要使用任何超级复杂和有限的组件库:)
用于反应的示例谷歌地图包装器(只是简单示例):
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;
然后你可以像这样使用它:
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;
示例信息窗口:
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 `$numpx`;
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;
【讨论】:
哇。那就是答案。谢谢楼主 谢谢,请注意,这些只是供您入门,而不是功能齐全的(复制/粘贴)组件。但我想您会明白的 :)【参考方案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
选项是我在 google 搜索中偶然发现的。
我还使用 CSS 对盒子进行了一些样式设置。也许我可以在 boxStyle 属性中完成这一切,但我宁愿尽可能多地将其保留在 CSS 中。 box-shadow 是唯一不能通过 CSS 工作的东西。
希望这对使用 react-google-maps
的人有所帮助。
【讨论】:
以上是关于Reactjs - 谷歌地图 - 样式信息窗口的主要内容,如果未能解决你的问题,请参考以下文章