2017-10-14 3 views
1

リーフレットプロジェクトでは、地図上の50個以上のマーカーを〜10個のチェックボックスでフィルタリングする必要があります。フィルタはマーカーの可視性を制御します。フィルタリングのためにクラス名を追加する以外に、DOMを分類する最適な方法はありますか?

私のアプローチは、各フィルタ条件の各マーカーに対応するクラス名を追加することです。スクリプトで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) 

} 
+2

これは時期尚早の最適化の場合のように聞こえます。 「私は心配です[X]はパフォーマンスを傷つけるでしょう」というフレーズは、あなたが実際にこれが当てはまるとは思わなかったことを意味する、将来の緊張です。 [正しいかもしれませんが、間違っているかもしれません。](https://softwareengineering.stackexchange.com/questions/80084/is-premature-optimization-really-the-root-of-all-evil)ブラウザは高速です、そして良くなっています。これが最初の問題であるかどうかを確認することを提案する。 – hunteke

+0

_ "スクリプトで50個以上のマーカーのクラス名を10個割り当てても、読み込み時間が遅くなることが心配です。"そして、実際にロード時間、または何らかの形でランタイムパフォーマンスを意味するのでしょうか? – CBroe

+0

ランタイムパフォーマンス - 現在は40個のマーカーしかありませんが、潜在的に5〜600個のマーカーまで増やすことができます。 – user3562812

答えて

0

を追加している私が使用してお勧めしますdata属性を明確に区別する必要がある場合を除いて、それぞれに異なるクラスを与えるのではなく、それぞれに属性を設定します。私は実際にあなたが最適化ヒットをしているかどうかは分かりませんが、保守性の観点から、別の開発者がなぜこれらのクラスがすべて浮動しているのか疑問に思うかもしれません。

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

次にあなたがこのように必要な要素(複数可)を選択できます:あなたはあなたのマーカーであまりにも多くのクラス名があるようにしたくない場合は、代わりにあなたを置き換えることができ

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

返事をありがとう。だから、1つの "データ名"はクラスのような複数のデータを含むことができますか、1つのデータごとに1つの "データ"属性を追加する必要がありますか? – user3562812

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(); 
    } 
} 
+0

返事をありがとう。私が正しく理解するなら、the_ハッシュは基準を満たすデータセットを含んでいますか? – user3562812

+0

うん!ここでの考え方は、キーがプロパティであり、配列にはキーの基準で記述された要素のリストが含まれているということです。 –

0

ライブラリがまだL.circleMarkerオブジェクトを追跡し、彼らは地図上残っていると考えてあなたは、マーカーに直接DOMを操作することは避けてください。

代わりに、removeをライブラリに正しく通知する必要があります。

マップに現在表示されているマーカーをフィルタリングする場合、DOMクエリに頼る必要がないため、事前にメタデータクラス(またはデータセット)を割り当てる必要があります。

あなたはL.geoJSON工場を通して、あなたの機能を構築し、自分のgeojson変数に結果GeoJSON Layer Groupを保つので、あなたは、単に以前に構築された各機能層の上にコールバック関数を適用することでeachLayerメソッドを使用することができます。

リーフレットがlayer.featureで参照しているように、各レイヤーのGeoJSONプロパティにアクセスできます。

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)); 
 
}
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"> 
 
<script src="https://unpkg.com/[email protected]/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>

関連する問題