使用自动完成搜索后缩放

Zoom after search using autocomplete

搜索后如何放大在地图上找到的值?我的代码是:

$("#txtSearch").autocomplete({
    source: setoresComerciais.features.map(function(d){
        return d.properties.sco_num_sc + " - " + d.properties.sco_dsc_loc
    }),
    select: function(event, ui){
        map.fitBounds(stComerciaisLayer.getBounds(ui.item.value));
    } 
});

首先,我得到return d.properties.sco_num_sc + " - " + d.properties.sco_dsc_loc,这个return,例如:"1 - FORTALEZA" 之后,我使用 select,哪里有参数 ui,什么时候做 ui.item.value return "1 - FORTALEZA",所以这个:

map.fitBounds(stComerciaisLayer.getBounds(ui.item.value));

其中:

stComerciaisLayer = L.geoJSON(setoresComerciais, {
                style: function (feature) {
                    return feature.properties && feature.properties.style;
                },
                onEachFeature: onEachFeature,
(...)

return 正是我想要的,搜索结果和放大结果,但不起作用。我做错了什么?

没用过这个插件,但无论如何都会尝试一下。

我建议您制作一个更复杂的 source,利用 source: function(request, response){} 功能。 See more.

$("#txtSearch").autocomplete({
  source: function(req, resp){
    var results = [];
    $.each(setoresComerciais.features.properties, function(k, p){
      if(p.sco_dsc_loc.toLowerCase().indexOf(req.term.toLowerCase()) == 0){
        results.push({
          label: p.sco_num_sc + " - " + p.sco_dsc_loc,
          value: p.sco_dsc_loc,
          properties: p
        });
      }
    });
    resp(results);
  },
  select: function(event, ui){
    map.fitBounds(stComerciaisLayer.getBounds(ui.item.value));
    return false;
  } 
});

这将确保每个潜在结果都有 { label, value } 对。如果您愿意,您也可以通过 select 中的 ui.item.properties 访问所有 properties

这也意味着您只传递 "FORTALEZA" 而不是 "1 - FORTALEZA" 如果它与地图数据中的标题匹配,这可能会使插件混淆。

如果您提供了示例数据或 jsFiddle,我会测试这个解决方案。


更新

多读了一些书。我看到了:

fitBounds(<LatLngBounds> bounds, <fitBounds options> options?)

Sets a map view that contains the given geographical bounds with the maximum zoom level possible.

map.fitBounds([
    [40.712, -74.227],
    [40.774, -74.125]
]);

对我来说,函数似乎需要一个数组而不是一个字符串。这是 return 由 .getBounds() 编辑的内容。然而,我读到的任何内容都表明 .getBounds() 不接受输入。所以我认为 stComerciaisLayer.getBounds(ui.item.value) 不会 return 你想要的值。


备注

您 select 给出了一个很好的答案,只是更新我的代码作为替代。

$("#txtSearch").autocomplete({
  source: function(req, resp){
    var results = [];
    $.each(setoresComerciais.features, function(k, f){
      var props = f.properties;
        if(props.sco_dsc_loc.toLowerCase().indexOf(req.term.toLowerCase()) == 0){
        results.push({
          label: props.sco_num_sc + " - " + props.sco_dsc_loc,
          value: props.sco_dsc_loc,
          properties: props,
          id: k
        });
      }
    });
    resp(results);
  },
  select: function(event, ui){
    var feature = setoresComerciais.features[ui.item.id];
    var featureLayer = L.geoJSON(feature)
    map.fitBounds(featureLayer.getBounds());
  } 
});

这一行:

map.fitBounds(stComerciaisLayer.getBounds(ui.item.value));

不会按预期工作。从 API 文档中,getBounds() 不接受任何参数,它只是 returns 您正在使用的层的边界。由于图层包含您所有的 geojson,因此这将不起作用。

相反,我们可以从您的 geojson FeatureCollection 中获取所选特征的 geojson,并从中创建一个图层(我们不需要将其添加到地图),以便我们可以找到它的边界并更新地图因此。

我们如何在 geojson 中获得正确的特征?有几种方法,我们可以使用字典,或者我们可以向自动完成功能源添加额外的数据(如其他答案中所建议的)。我会跟随另一个答案的领导,但使用功能的增量并继续使用 .map() :

source: setoresComerciais.features.map(function(d,i){
    return {
      label: d.properties.sco_num_sc + " - " + d.properties.sco_dsc_loc, 
      id: i 
    };

这里.map有两个变量:d是正在处理的特征数组中的当前项,i是那个特征的索引。使用索引,我们可以轻松访问要素数组中的适当项目,从中创建一个图层,并将地图边界与该要素的图层相匹配:

select: function(event, ui){
    var feature = setoresComerciais.features[ui.item.id]; // get the geojson
    var featureLayer = L.geoJSON(feature)  // create a layer from it
    map.fitBounds(featureLayer.getBounds()); // resize the map
} 

总而言之,这给了我们:

    $("#txtSearch").autocomplete({
        source: setoresComerciais.features.map(function(d,i){
            return {label: d.properties.sco_num_sc + " - " + d.properties.sco_dsc_loc, id: i };
        }),
        select: function(event, ui){
            var feature = setoresComerciais.features[ui.item.id];
            var featureLayer = L.geoJSON(feature)
            map.fitBounds(featureLayer.getBounds());
        } 
    });