我使用Leaflet.Control.Search按GeoJSON功能搜索标记,它可以正常工作。现在我必须输入第一个字母来查找标记,但我想从下拉列表中选择它们,其中包含所有标记。它是这样做的吗?
答案 0 :(得分:2)
如果您想要一个包含所有标记的下拉列表,最好创建一个自定义控件,而不是尝试修改Leaflet.Control.Search。使用包含所有标记的select
元素创建一个控件有点复杂,但肯定比调整其他人已完成项目的代码简单得多。
首先创建一个空控件:
var selector = L.control({
position: 'topright'
});
要将内容放在控件中,您可以使用控件的.onAdd
方法。使用L.DomUtil.create
为控件创建容器div,在此上下文中将自动分配类leaflet-control
,允许div中的任何内容显示在地图上,其行为就像控件应该表现的那样。然后在div中创建一个select
元素。如果需要,请为其提供默认选项。最重要的是,给它一个id
,以便以后可以参考:
selector.onAdd = function(map) {
var div = L.DomUtil.create('div', 'mySelector');
div.innerHTML = '<select id="marker_select"><option value="init">(select item)</option></select>';
return div;
};
现在控件知道在添加到地图时要做什么,请继续添加:
selector.addTo(map);
要在选择器中添加所有标记作为选项,您可以使用.eachLayer
method,它遍历组中的所有标记并为每个标记调用一个函数。对于每个图层,使用上面指定的option
创建select
元素并将其附加到id
元素。假设您已经创建了一个名为markerLayer
的GeoJSON图层,它具有一个名为STATION
的属性,您希望将其用作选项文本,它将如下所示:
markerLayer.eachLayer(function(layer) {
var optionElement = document.createElement("option");
optionElement.innerHTML = layer.feature.properties.STATION;
optionElement.value = layer._leaflet_id;
L.DomUtil.get("marker_select").appendChild(optionElement);
});
在此,我们依赖于每个图层在创建时都会分配一个唯一的内部ID编号_leaflet_id
这一事实。我们将每个选项的value
属性设置为相应的图层_leaflet_id
,以便在选择该选项时,我们可以访问该标记。
最后,为了让控件在您选择其中一个选项时实际执行某些操作,请使用选择器元素的id
添加一些事件侦听器:
var marker_select = L.DomUtil.get("marker_select");
L.DomEvent.addListener(marker_select, 'click', function(e) {
L.DomEvent.stopPropagation(e);
});
L.DomEvent.addListener(marker_select, 'change', changeHandler);
使用click
方法的stopPropagation
侦听器是为了防止点击选择器传播到地图(如果它们与地图窗格重叠),这可能会立即取消选择您要突出显示的图层。 change
侦听器将运行处理函数,您可以将其设置为执行任何操作。在这里,我已将其设置为在选择相应选项时打开标记的弹出窗口:
function changeHandler(e) {
if (e.target.value == "init") {
map.closePopup();
} else {
markerLayer.getLayer(e.target.value).openPopup();
}
}
那就是它!以下是所有这些合作的例子:
http://jsfiddle.net/nathansnider/ev3kojon/
修改强>
如果您使用的是MarkerCluster插件,则可以使用.zoomToShowLayer
method修改更改处理函数以使用聚簇标记:
function changeHandler(e) {
if (e.target.value == "init") {
map.closePopup();
} else {
var selected = markerLayer.getLayer(e.target.value);
markerClusterLayer.zoomToShowLayer(selected, function() {
selected.openPopup();
})
}
}
示例:
http://jsfiddle.net/nathansnider/oqk6u0sL/
(我还更新了原始代码和示例以使用.getLayer
方法而不是._layers[e.target.value]
,因为这是一种基于其ID访问标记的更简洁方法。
答案 1 :(得分:1)
有一种方法可以稍微修改Leaflet-search插件,以便在用户点击放大镜按钮时显示完整的标记列表(即当用户扩展搜索控件时)。
好像为0输入的字母触发了搜索。
在不修改插件代码的情况下使用选项minLength: 0
不会在不打字的情况下触发搜索。
L.Control.Search.mergeOptions({
minLength: 0 // Show full list when no text is typed.
});
L.Control.Search.include({
_handleKeypress: function(e) {
switch (e.keyCode) {
case 27: //Esc
this.collapse();
break;
case 13: //Enter
if (this._countertips == 1)
this._handleArrowSelect(1);
this._handleSubmit(); //do search
break;
case 38: //Up
this._handleArrowSelect(-1);
break;
case 40: //Down
this._handleArrowSelect(1);
break;
case 37: //Left
case 39: //Right
case 16: //Shift
case 17: //Ctrl
//case 32://Space
break;
case 8: //backspace
case 46: //delete
this._autoTypeTmp = false;
if (this._collapsing) { // break only if collapsing.
break;
}
default: //All keys
this._doSearch(); // see below
}
},
// externalized actual search process so that we can trigger it after control expansion.
_doSearch: function() {
if (this._input.value.length)
this._cancel.style.display = 'block';
else
this._cancel.style.display = 'none';
if (this._input.value.length >= this.options.minLength) {
var that = this;
clearTimeout(this.timerKeypress);
this.timerKeypress = setTimeout(function() {
that._fillRecordsCache();
}, this.options.delayType);
} else
this._hideTooltip();
},
expand: function(toggle) {
toggle = typeof toggle === 'boolean' ? toggle : true;
this._input.style.display = 'block';
L.DomUtil.addClass(this._container, 'search-exp');
if (toggle !== false) {
this._input.focus();
this._map.on('dragstart click', this.collapse, this);
}
this.fire('search_expanded');
this._doSearch(); // Added to trigger a search when expanding the control.
return this;
},
collapse: function() {
this._hideTooltip();
this._collapsing = true; // added to prevent showing tooltip when collapsing
this.cancel();
this._collapsing = false; // added to prevent showing tooltip when collapsing
this._alert.style.display = 'none';
this._input.blur();
if (this.options.collapsed) {
this._input.style.display = 'none';
this._cancel.style.display = 'none';
L.DomUtil.removeClass(this._container, 'search-exp');
if (this.options.hideMarkerOnCollapse) {
this._markerLoc.hide();
}
this._map.off('dragstart click', this.collapse, this);
}
this.fire('search_collapsed');
return this;
}
});
在实例化L.Control.Search
之前,在JavaScript中包含此代码。
演示:http://jsfiddle.net/ve2huzxw/190/
此解决方案的一大缺点是标记列表是在地图容器中构建的。因此,如果它太大,它将在底部被裁剪,而真正的选择(下拉)输入将“溢出”超出容器,如在nathansnider的解决方案中。