除了为过滤添加类名之外,还有更好的方法来分类DOM吗?

时间:2017-10-14 04:43:56

标签: javascript leaflet

我正在研究传单项目,其中地图上的50多个标记需要使用~10个复选框进行过滤。过滤器将控制标记的可见性。

现在,我的方法是为每个过滤条件的每个标记添加相应的类名。我担心在脚本中为超过50个标记分配10个类名会减慢加载时间。

这是链接 http://jbk1109.github.io/hiking-info.html

这是我的代码:标记是基于geojson数据创建的,类名是在样式函数中添加的

<div id="distanceFilterContainer">

<input type="checkbox" name="checkboxField" class ="distanceFilter" id="short">
<label> Under 3 miles </label>

<input type="checkbox" name="checkboxField" class ="distanceFilter" id="medium">
<label> 3-8 miles </label>

<input type="checkbox" name="checkboxField" class ="distanceFilter" id="long">
<label> 8-12 miles </label>

</div>


geojson = L.geoJson(data,{
    onEachFeature: featureEvent,
    pointToLayer:function(feature, latlng){
        // console.log(latlng.lat)
        return L.circleMarker(latlng, geojsonMarkerOptions);
    },
    style: style
}).addTo(mymap)

function style(feature){
    console.log(feature)
    var length;
    if (feature.properties.Length <= 3.0){
        length = " short"
    }
    else if (feature.properties.Length > 3 && feature.properties.Length < 8)
    {
        length = " medium"
    }
    else if (feature.properties.Length >= 8.0){
        length =" long"
    }
    console.log(feature.properties.Name + length)
    return {className : feature.properties.Name + length}

}

document.getElementById("short").addEventListener("change",handleDistanceFilter)
    document.getElementById("medium").addEventListener("change",handleDistanceFilter)
    document.getElementById("long").addEventListener("change",handleDistanceFilter)

function handleDistanceFilter(e){
    var x = e.target.id
    console.log(x)
    if (!e.target.checked){
        var filtered = document.getElementsByClassName(x)
        console.log(x)
        for (var i =0; i< filtered.length; i++){
            filtered[i].classList.remove("hide")
            // filtered[i].style.visibility = 'visible';
        }
    }
    else{
        var filtered = document.getElementsByClassName(x)
        for (var i =0; i< filtered.length; i++){
            console.log(x)
            filtered[i].classList.add("hide")
            // console.log(filtered)
            // filtered[i].style.visibility = 'hidden';
        }
    }
    // console.log(e.target.checked)

}

3 个答案:

答案 0 :(得分:0)

我建议为每个属性使用data属性,而不是给每个属性一个不同的类,除非它们需要进行明确的样式化。我实际上并不知道你是否正在进行优化,但从可维护性的角度来看,另一位开发人员可能会质疑为什么所有这些类都会浮出水面。

element.setAttribute('data-name', x);

然后你可以用这种方式选择所需的元素:

document.querySelectorAll('[data-name=' + x + ']');

答案 1 :(得分:0)

如果你不希望标记中有太多的类名,你可以用一个用关键字作为过滤器来更新散列的样式函数替换你的样式函数,而值是你想要的元素ID。

示例:

var the_hash = {"short": [], ...}
function style(feature){
    if (feature.isShort())
        the_hash["short"].push(feature);
}

function handleFilter(filter) {
    var elements = the_hash[filter];
    for (var i = 0, item; item = elements[i]; i++) {
        item.doSomething();
    }
}

答案 2 :(得分:0)

使用Leaflet,您应该避免直接操作DOM作为标记,因为库仍然跟踪L.circleMarker个对象,并认为它们仍然在地图上。

相反,您应该只是remove它们,以便正确通知库。

至于过滤当前在地图上显示的标记,也不需要求助于DOM查询,因此必须事先分配一些元数据类(或数据集)以便于进行此类查询。

由于您是通过L.geoJSON工厂制作功能并将结果GeoJSON Layer Group保存到geojson变量中,因此您只需使用eachLayer方法即可应用回调在先前构建的每个要素图层上运行。

然后您可以访问每个图层的GeoJSON属性,因为它由layer.feature中的Leaflet引用。

&#13;
&#13;
var map = L.map("map");

var geoJSONdata = {
  "type": "FeatureCollection",
  "features": [{"type": "Feature","properties": {"Length": 8},"geometry": {"type": "Point","coordinates": [-121.7350, 46.7860]}},
  {"type": "Feature","properties": {"Length": 12},"geometry": {"type": "Point","coordinates": [-121.0750, 48.4755]}},
  {"type": "Feature","properties": {"Length": 3.2},"geometry": {"type": "Point","coordinates": [-121.8913, 46.6664]}},
  {"type": "Feature","properties": {"Length": 6.2},"geometry": {"type": "Point","coordinates": [-123.2321, 47.5066]}},
  {"type": "Feature","properties": {"Length": 8},"geometry": {"type": "Point","coordinates": [-121.6925, 48.8469]}},
  {"type": "Feature","properties": {"Length": 7.2},"geometry": {"type": "Point","coordinates": [-120.7354, 48.5162]}}]
};

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);

var geoJSONlayerGroup = L.geoJSON(geoJSONdata, {
    onEachFeature: onEachFeature
  }).addTo(map);

map.fitBounds(geoJSONlayerGroup.getBounds());

var lengthInput = document.getElementById('length');
var lengthDisplay = document.getElementById('length2');

function filterFeatures() {
  var length = parseFloat(lengthInput.value);
  lengthDisplay.innerHTML = length;
  
  geoJSONlayerGroup.eachLayer(function (layer) {
    // Access the layer associated feature GeoJSON properties.
    if (layer.feature.properties.Length <= length) {
      layer.addTo(map); // Directly add to map, instead of using CSS classes.
    } else {
      layer.remove(); // Directly remove from map.
    }
  });
}

filterFeatures();

lengthInput.addEventListener('input', filterFeatures);

function onEachFeature(feature, layer) {
  layer.bindPopup(JSON.stringify(feature.properties));
}
&#13;
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.2.0/dist/leaflet.css">
<script src="https://unpkg.com/leaflet@1.2.0/dist/leaflet-src.js"></script>

<input type="range" min="0" max="12" step="0.5" id="length" />
<label for="length">Max length (<span id="length2"></span>)</label>

<div id="map" style="height: 170px;"></div>
&#13;
&#13;
&#13;