我在React前端中使用Mapbox GL JS,并使用一个单独的组件来显示Mapbox弹出窗口,如下所示(示例代码缩短了):
import React from 'react';
import mapboxgl from 'mapbox-gl';
mapboxgl.accessToken = CONFIG.MAPBOX.ACCESS_TOKEN;
// Pass router context to components that are rendered tith React.render()
function withContext(WrappedComponent, context){
class ContextProvider extends React.Component {
getChildContext() {
return context;
}
render() {
return <WrappedComponent {...this.props} />
}
}
ContextProvider.childContextTypes = {};
Object.keys(context).forEach(key => {
ContextProvider.childContextTypes[key] = PropTypes.any.isRequired;
});
return ContextProvider;
}
class InteractiveMap extends React.Component {
constructor(props) {
this.map;
this.mapSource;
this.popup;
this.popupContainer;
this.hasOpenPopup = false;
}
// This make sure you have router in your this.context
static contextTypes = {
router: PropTypes.object.isRequired
}
addCustomPopup(feature) {
if (feature) {
// Pass router context
const MapPopupWithContext = withContext(MapPopup, this.context);
ReactDOM.render(
<Provider store={STORE}>
<MapPopupWithContext
feature={feature}
extended={true}
onClick={(type, item, coordinates) => this.handlePopUpLink(type, item, coordinates)}
/>
</Provider>,
this.popupContainer,
(() => {
this.hasOpenPopup = true;
ReactDOM.unmountComponentAtNode(this.tooltipContainer);
})
);
}
}
handlePopUpLink(item) {
// open other react component
this.hasOpenPopup = false;
}
this.map = new mapboxgl.Map({
container: this.mapContainer
});
this.map.on('load', () => {
this.map.addSource('features', {
type : 'geojson',
data : this.mapSource
});
});
// Add Popup containers with z-index
this.popupContainer = document.createElement('div');
this.popupContainer.classList.add('b-map-popup', 'is-popup');
// Add Popup
this.popup = new mapboxgl.Popup({
closeButton : false,
closeOnClick: false,
anchor : 'bottom'
})
.setDOMContent(this.popupContainer)
.setLngLat([0,0])
.addTo(this.map);
this.popup.on('close', (e) => {
// always fires on popup link click
console.log('popup close');
});
// Add layer
this.map.addLayer({
id: layerID,
type: 'symbol',
source: 'features',
layout: {
'icon-image' : 'layer',
'icon-size' : 0.5,
'icon-allow-overlap' : true,
'icon-ignore-placement': true,
'text-allow-overlap' : true
}
});
// Open clicked feature in popup
this.map.on('click', (e) => {
const feature = this.map.queryRenderedFeatures(e.point, {
radius: 100,
layers: 'layer'
});
if (!feature) {
// If on the map, remove the current popup
this.popup.remove();
this.hasOpenPopup = false;
} else {
if (feature.geometry.type === 'Point') {
e.lngLat = feature.geometry.coordinates;
}
this.popup.setLngLat(e.lngLat);
this.popup.addTo(this.map);
this.addCustomPopup(feature);
}
});
render() {
return (
<div className={'b-map'} ref={el => this.mapContainer = el} />
);
}
}
class MapPopup extends React.Component {
onClick(event, item) {
const { onClick } = this.props;
// Disable on popup close here
onClick(item);
}
render() {
const { feature } = this.props;
// Content
popupContent = (
<div className="b-map-popup__content">
<div className='b-map-popup__content-wrap'>
<h1 className='b-map-popup__title'>{feature.title}</h1>
<a className="b-map-popup__button" onClick={(e) => this.onClick(e, clickItem)}>{'Lees meer'}</a>
</div>
</div>
);
return (
<div className="b-map-popup__wrapper">
{popupContent}
<span className="b-map-popup__arrow"></span>
</div>
);
}
}
MapPopup.propTypes = {
feature : PropTypes.object.isRequired,
onClick : PropTypes.func
}
在弹出窗口中,有一些与其他React组件交互的链接。但是,单击这些链接总是会触发弹出close
事件。
如何控制何时关闭弹出窗口?
我发现这个old doc也需要jQuery,但是主要区别是我使用setdomcontent用HTML内容填充弹出窗口。
非常感谢任何指针!
实际上,我发现close
事件不是由链接本身触发的,而是由链接触发的map.flyTo()
事件触发的。
所以我的问题实际上应该是:如何防止由flyTo触发的弹出关闭事件(触发多个地图事件,例如:移动,zoomstart,zoom,zoomend,pitchstart,pitch,pitchend)?