单击弹出窗口中的链接时禁用弹出窗口关闭事件

时间:2018-09-14 08:50:24

标签: javascript onclick popup mapbox-gl-js

我在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内容填充弹出窗口。

非常感谢任何指针!

编辑1

实际上,我发现close事件不是由链接本身触发的,而是由链接触发的map.flyTo()事件触发的。

所以我的问题实际上应该是:如何防止由flyTo触发的弹出关闭事件(触发多个地图事件,例如:移动,zoomstart,zoom,zoomend,pitchstart,pitch,pitchend)?

0 个答案:

没有答案