距离地图中心太远时 Mapbox 标记消​​失

Mapbox markers disappearing when too far away from map center

我有一个带有标记的 Mapbox 地图(我也使用 MarkerCluster)。我在 JavaScript 中得到这些 HTML 标记来确定它们的位置(从视口,而不是它们的坐标),所以我可以添加一些不在视口中的标记指示符。但我意识到当我离标记太远时(例如缩放或拖动地图时),标记就不会出现在 HTML!这似乎是正常行为,因为我可以在官方示例中看到同样的事情发生。

那么,问题来了:有什么方法可以防止这种行为并始终在 HTML 中添加标记?

这是 JavaScript:(我使用 mapbox.js 和 leaflet.markercluster)

var places = {
    "type": "FeatureCollection",
    "features": [{
        "type": "Feature",
        "properties": {
            "description": ">Test 1"
        },
        "geometry": {
            "type": "Point",
            "coordinates": [-1.6313898, 47.2005156]
        }
    }, {
        "type": "Feature",
        "properties": {
            "description": "Test 2"
        },
        "geometry": {
            "type": "Point",
            "coordinates": [2.3279346, 48.8960698]
        }
    }, {
        "type": "Feature",
        "properties": {
            "description": "Test 3"
        },
        "geometry": {
            "type": "Point",
            "coordinates": [2.7391394, 48.7238554]
        }
    }, {
        "type": "Feature",
        "properties": {
            "description": "Test 4"
        },
        "geometry": {
            "type": "Point",
            "coordinates": [55.4933757, -20.9034031]
        }
    }]
};

L.mapbox.accessToken = 'pk.eyJ1Ijoic3RlcmVvc3VwZXIiLCJhIjoiY2lyM2JnMDIwMDAxM2k0bWNndmUzeTFhbSJ9.UZ-XuPASxGVtYFSqdVyppg';

var map = L.mapbox.map('map', null, {minZoom: 3, maxZoom: 16, center: [46, 8], zoom: 5, scrollWheelZoom: false, maxBounds: [[-100.0,-100.0],[100.0,100.0]]});
L.mapbox.styleLayer('mapbox://styles/stereosuper/cir3bgtaz001wjcnntu6n2axw').addTo(map);

var markers = L.mapbox.featureLayer(places);
var icon = L.divIcon({ iconSize: [30, 30], popupAnchor: [0, -20] });
markers.eachLayer(function(l){ l.setIcon(icon); });

var clusterPlaces = new L.MarkerClusterGroup({
    iconCreateFunction: function(cluster){
        return new L.DivIcon({ iconSize: [30, 30], html: '<div class="marker-cluster"><span>'+cluster.getChildCount()+'</span></div>' });
    }
});
clusterPlaces.addLayer(markers).addTo(map);

map.on('moveend', function(e){
    var htmlMarkers = $('.leaflet-marker-icon'),
        xCenter = $(window).width()/2, yCenter = $(window).height()/2;

    if($('.map-indicator').length){
        $('.map-indicator').remove();
    }

    htmlMarkers.each(function(i){
        var thisMarker = $(this),
            thisCluster = thisMarker.find('span').length,
            thisMarkerHtml = thisCluster ? thisMarker.find('span').html() : 1;
        var top = thisMarker.offset().top, left = thisMarker.offset().left;
        var indicator = '<button class="map-indicator map-indicator-'+i+'"><span>'+thisMarkerHtml+'</span></button>';
        var newLeft, newTop, angle, distance;
        var mapHtml = $('#map');

        if(top + thisMarker.height() < 0){
            mapHtml.append(indicator)
            if(left > xCenter){
                distance = (left-xCenter) * (yCenter/(yCenter-top));
                angle = Math.atan(distance/yCenter)*180/Math.PI;
                newLeft = xCenter + distance;
                if(newLeft > $(window).width() - 40) newLeft = $(window).width() - 40;
            }else{
                distance = (xCenter-left) * (yCenter/(yCenter-top));
                angle = - Math.atan(distance/yCenter)*180/Math.PI;
                newLeft = xCenter - distance;
                if(newLeft < 40) newLeft = 40;
            }
            $('.map-indicator-'+i).css({'top': '10px', 'left':  newLeft + 'px', 'bottom': 'auto', 'right': 'auto', '-webkit-transform': 'rotate('+angle+'deg)', 'transform': 'rotate('+angle+'deg)'}).addClass('top').removeClass('bottom', 'left', 'right');
        }else if(top > $(window).height()){
            mapHtml.append(indicator)
            if(left > xCenter){
                distance = (left-xCenter) * (yCenter/(yCenter+(top-$(window).height())));
                angle = - Math.atan(distance/yCenter)*180/Math.PI;
                newLeft = xCenter + distance;
                if(newLeft > $(window).width() - 40) newLeft = $(window).width() - 40;
            }else{
                distance = (xCenter-left) * (yCenter/(yCenter+(top-$(window).height())));
                angle = Math.atan(distance/yCenter)*180/Math.PI;
                newLeft = xCenter - distance;
                if(newLeft < 40) newLeft = 40;
            }
            $('.map-indicator-'+i).css({'bottom': '10px', 'left':  newLeft + 'px', 'top': 'auto', 'right': 'auto', '-webkit-transform': 'rotate('+angle+'deg)', 'transform': 'rotate('+angle+'deg)'}).addClass('bottom').removeClass('top', 'left', 'right');
        }else if(left + thisMarker.width() < 0){
            mapHtml.append(indicator)
            if(top < yCenter){
                distance = (yCenter-top) * (xCenter/(xCenter-left));
                angle = Math.atan(distance/xCenter)*180/Math.PI;
                newTop = yCenter - distance;
                if(newTop < 0) newTop = 0;
            }else{
                distance = (top-yCenter) * (xCenter/(xCenter-left));
                angle = - Math.atan(distance/xCenter)*180/Math.PI;
                newTop = yCenter + distance;
                if(newTop > $(window).height()) newTop = $(window).height() - thisMarker.height();
            }
            $('.map-indicator-'+i).css({'top': newTop, 'left': '10px', 'bottom': 'auto', 'right': 'auto', '-webkit-transform': 'rotate('+angle+'deg)', 'transform': 'rotate('+angle+'deg)'}).addClass('left').removeClass('bottom', 'top', 'right');
        }else if(left > $(window).width()){
            mapHtml.append(indicator)
            if(top < yCenter){
                distance = (yCenter-top) * (xCenter/(xCenter+(left-$(window).width())));
                angle = - Math.atan(distance/xCenter)*180/Math.PI;
                newTop = yCenter - distance;
                if(newTop < 0) newTop = 0;
            }else{
                distance = (top-yCenter) * (xCenter/(xCenter+(left-$(window).width())));
                angle = Math.atan(distance/xCenter)*180/Math.PI;
                newTop = yCenter + distance;
                if(newTop > $(window).height()) newTop = $(window).height() - thisMarker.height();
            }
            $('.map-indicator-'+i).css({'top': newTop, 'left': 'auto', 'bottom': 'auto', 'right': '10px', '-webkit-transform': 'rotate('+angle+'deg)', 'transform': 'rotate('+angle+'deg)'}).addClass('right').removeClass('bottom', 'left', 'top');
        }

        $('.map-indicator-'+i).on('click', function(e){
            var coordinates = map.layerPointToLatLng(thisMarker.context._leaflet_pos);
            map.panTo(coordinates);
        });
    });
});

提前致谢

您猜对了,Leaflet.markercluster 插件默认删除远离您视口的标记和簇。

您可以在创建标记群集组时使用 removeOutsideVisibleBounds 选项来禁用此行为。

请注意,在高缩放时,这可能会降低您的浏览器性能,因为您的地图上会有很多标记,这是 Leaflet.markercluster 试图避免的事情之一。