Leaflet 和 Mapbox:通过 Javascript 添加时按钮不起作用

Leaflet and Mapbox: Buttons not working when added via Javascript

有人知道为什么单击按钮后不会在地图上添加或删除叠加层吗? Full PLNKR here

HTML

<div id="toggleButtons" style="display: none">
 <button id="add">Add Overlays</button>
 <button id="remove">Remove Overlays</button>
</div>

Javascript

L.Control.GroupedLayers.include({
addOverlays: function () {
    for (var i in this._layers) {
        if (this._layers[i].overlay) {
            if (!this._map.hasLayer(this._layers[i].layer)) {
                this._map.addLayer(this._layers[i].layer);
            }
        }
    }
},
removeOverlays: function () {
    for (var i in this._layers) {
        if (this._layers[i].overlay) {
            if (this._map.hasLayer(this._layers[i].layer)) {
                this._map.removeLayer(this._layers[i].layer);
            }
        }
    }
 }
});

var control = new L.Control.GroupedLayers(ExampleData.Basemaps, {
'Landmarks': {
    'Cities': ExampleData.LayerGroups.cities,
    'Restaurants': ExampleData.LayerGroups.restaurants
},
'Random': {
    'Dogs': ExampleData.LayerGroups.dogs,
    'Cats': ExampleData.LayerGroups.cats
}
}).addTo(map);

L.DomEvent.addListener(L.DomUtil.get('add'), 'click', function () {
control.addOverlays();
});

L.DomEvent.addListener(L.DomUtil.get('remove'), 'click', function () {
control.removeOverlays();
});

然后我添加了 mapbox legendControl.addLegend 方法 (from the mapbox API documentation)

map.legendControl.addLegend(document.getElementById('toggleButtons').innerHTML);

虽然按钮显示在地图中,但它们的点击属性不起作用。有什么线索吗?谢谢!

这里需要遵循授权策略..

document.querySelector('body').addEventListener('click',   function(event) {
  if (event.target.id.toLowerCase() === 'add') {
    control.addOverlays();
  }
  if (event.target.id.toLowerCase() === 'remove') {
    control.removeOverlays();
  }
});

您不是 'adding' 具有 javascript 的按钮,您正在制作它们的副本并将副本放入 legendControl。带有事件处理程序的实际按钮仍存在于 DOM 中,但已隐藏,因为您已将 display: none 添加为内联样式。你想要做的是 select 按钮并将它们从正文中删除:

var buttons = document.getElementById('toggleButtons');
document.body.removeChild(buttons);

然后您可以将它们添加到图例中并附加事件处理程序:

var legendControl = L.mapbox.legendControl().addTo(map);

legendControl.addLegend(buttons.innerHTML);

L.DomEvent.addListener(L.DomUtil.get('add'), 'click', function () {
    control.addOverlays();
});

L.DomEvent.addListener(L.DomUtil.get('remove'), 'click', function () {
    control.removeOverlays();
});

Plunker 上的工作示例:http://plnkr.co/edit/7pDkrZbS7Re1YshKZSLs?p=preview

PS。我很困惑为什么你会滥用 mapbox 的图例控件 class 添加两个按钮。如果您需要自定义控件,您可以使用传单的 L.Control class 创建一个。它使您免于加载您不使用的图例控件 class,因此会膨胀。

编辑:正如下面评论中所承诺的,将此解决方案滚动到您自己的自定义控件中的示例。我将在代码中的注释中进行更多解释,但总体思路是采用基本的 L.Control 界面并向其添加功能和 DOM 生成:

// Create a new custom control class extended from L.Control
L.Control.Toggle = L.Control.extend({

    // Have some default options, you can also change/set
    // these when intializing the control
    options: {
        position: 'topright',
        addText: 'Add',
        removeText: 'Remove'
    },

    initialize: function (control, options) {
        // Add the options to the instance
        L.setOptions(this, options);
        // Add a reference to the layers in the layer control
        // which is added to the constructor upon intialization
        this._layers = control._layers;
    },

    onAdd: function (map) {
        // Create the container
        var container = L.DomUtil.create('div', 'control-overlaystoggle'),
            // Create add button with classname, append to container
            addButton = L.DomUtil.create('button', 'control-overlaystoggle-add', container),
            // Create remove button with classname, append to container
            removeButton = L.DomUtil.create('button', 'control-overlays-toggleremove', container);

        // Add texts from options to the buttons
        addButton.textContent = this.options.addText;
        removeButton.textContent = this.options.removeText;

        // Listen for click events on button, delegate to methods below
        L.DomEvent.addListener(addButton, 'click', this.addOverlays, this);
        L.DomEvent.addListener(removeButton, 'click', this.removeOverlays, this);

        // Make sure clicks don't bubble up to the map
        L.DomEvent.disableClickPropagation(container);

        // Return the container
        return container;
    },

    // Methods to add/remove extracted from the groupedLayerControl
    addOverlays: function () {
        for (var i in this._layers) {
            if (this._layers[i].overlay) {
                if (!this._map.hasLayer(this._layers[i].layer)) {
                    this._map.addLayer(this._layers[i].layer);
                }
            }
        }
    },

    removeOverlays: function () {
        for (var i in this._layers) {
            if (this._layers[i].overlay) {
                if (this._map.hasLayer(this._layers[i].layer)) {
                    this._map.removeLayer(this._layers[i].layer);
                }
            }
        }
    }

});

现在您可以按如下方式使用您的新控件:

// Create a new instance of your layer control and add it to the map
var layerControl = new L.Control.GroupedLayers(baselayers, overlays).addTo(map);

// Create a new instance of your toggle control
// set the layercontrol and options as parameters
// and add it to the map
var toggleControl = new L.Control.Toggle(layerControl, {
    position: 'bottomleft',
    addText: 'Add overlays',
    removeText: 'Remove overlays'
}).addTo(map);

我知道,这既快速又肮脏,但它应该让您大致了解 L.Control class 可以做什么。

这是一个关于 Plunker 的工作示例:http://plnkr.co/edit/7pDkrZbS7Re1YshKZSLs?p=preview

这里是 L.Control 的参考:http://leafletjs.com/reference.html#control