【问题标题】:Filtering Leaflet Map based on dropdown selection in D3基于D3中的下拉选择过滤Leaflet Map
【发布时间】:2021-12-17 16:07:25
【问题描述】:

我正在尝试根据下拉列表中的行业选择过滤我的地图标记图层,我在此处的 html 中手动引用了该列表 - 我想最初保留预加载的标记数据并提供一个选项通过从下拉列表中选择来过滤标记。

<select class="dropdown" id="selDataset">
              <option value="" selected="selected">Industry</option>
              <option value ="ind1">Accomodation and Food Services</option>
              <option value ="ind2">Educational Services</option>
              <option value ="ind3">Administrative and Support and Waste Management and Remediation Services</option>
              <option value ="ind4">Professional, Scientific, and Technical Services</option>
              <option value ="ind5">Manufacturing</option>
              <option value ="ind6">Construction</option>
              <option value ="ind7">Health Care and Social Assistance</option>
              <option value ="ind8">Wholesale Trade</option>
              <option value ="ind9">Information</option>
     </select>
          

这是我的 .js 代码 - 我的猜测是我需要定义一个包含第一个 for 循环的函数,如果选择过滤该行业的 lat,lng,则设置一个 if else 语句,否则默认返回所有.我只是不确定如何引用 html 下拉选择来过滤标记。我已经通过 D3.js 实现了用于表格过滤的下拉菜单,并且之前使用过覆盖层,但是我找不到使用传单标记层的实现。

// Creating map object
var myMap = L.map("map", {
  center: [40.73, -74.0059],
  zoom: 11
});

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

var data = [{
    lat: 40.75,
    lng: -73.99,
    BusinessName: 'Bank LLC',
    Industry: 'Banking'
  },
  {
    lat: 40.73,
    lng: -73.97,
    BusinessName: 'Some Hotel',
    Industry: 'Hospitality'
  },
  {
    lat: 40.74,
    lng: -74.00,
    BusinessName: 'Other Hotel',
    Industry: 'Hospitality'
  }
];

// Create a new marker cluster group
var markers = L.layerGroup();

// Loop through data
for (var i = 0; i < data.length; i++) {
  // Set the latitude, longitude property to a variable
  var latitude = data[i].lat;
  var longitude = data[i].lng;
  var popText = ("<h3>" + data[i].BusinessName + "</h3><h3>Industry: " + data[i].Industry + "</h3>");
  // var industry = data[i].Industry;
  // var mySelector = $("#Industry").val();
  // Check for location property

  if (latitude) {
    // Add a new marker to the cluster group and bind a pop-up
    markers.addLayer(L.marker([latitude, longitude])
      .bindPopup(popText));
  };
}
// Add our marker cluster layer to the map
myMap.addLayer(markers);
#map {
  height: 400px;
  width: 600px;
}
 <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
   integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
   crossorigin=""/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet-src.js"></script>

<div id="map"></div>

【问题讨论】:

  • 如果您可以创建代码的minimal reproducible example,最好在runnable stack snippet 中使用一些样本/虚拟数据来帮助我们理解问题,这将非常有帮助。这样,我们可以更轻松地回答您的问题,您也更有可能得到一个好的答案!
  • @RubenHelsloot 嗨鲁本,谢谢你的回复。我不是 100% 确定如何在我的 js 脚本中补充数据以提供运行代码 sn-p 而不会显着改变我的 .js 文件以在不引用源文件的情况下考虑数据读入,我认为这是寻求的组成部分解决方案。但是,我确实有一个正在运行的 heroku 应用程序就足够了。
  • 您能否提供几行来自 CSV 文件的示例数据?它们可以有虚拟值,这只是结构。
  • @RubenHelsloot ibb.co/m5SKxZq

标签: d3.js leaflet


【解决方案1】:

D3 的工作方式不是从头开始重新绘制所有内容,而是通过更新选择使用的基础数据:

  1. 有一个函数draw() 可以绘制给定的数据。在draw() 内,确保您还删除了旧图纸的任何残留物;
  2. 使用 D3 在下拉菜单中设置正确的选项(比硬编码更好,因为将来定义可能会改变);
  3. 每当下拉值发生变化时,调用draw 并使用基础数据的子集;
  4. 致电draw() 提供所有数据以提供初始标记。

对于您的代码,请查看数组函数,例如 Array.prototype.mapArray.prototype.filter,因为它们在处理此类数据时通常非常有用。

// Creating map object
var myMap = L.map("map", {
  center: [40.73, -74.0059],
  zoom: 11
});

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

var allData = [{
    lat: 40.75,
    lng: -73.99,
    BusinessName: 'Bank LLC',
    Industry: 'Banking'
  },
  {
    lat: 40.73,
    lng: -73.97,
    BusinessName: 'Some Hotel',
    Industry: 'Hospitality'
  },
  {
    lat: 40.74,
    lng: -74.00,
    BusinessName: 'Other Hotel',
    Industry: 'Hospitality'
  }
];

// Create a new marker cluster group
var markers = L.layerGroup();
// Add our marker cluster layer to the map
myMap.addLayer(markers);

function draw(data) {
  // Start fresh
  markers.clearLayers();

  // Loop through data
  for (var i = 0; i < data.length; i++) {
    // Set the latitude, longitude property to a variable
    var latitude = data[i].lat;
    var longitude = data[i].lng;
    var popText = ("<h3>" + data[i].BusinessName + "</h3><h3>Industry: " + data[i].Industry + "</h3>");
    // var industry = data[i].Industry;
    // var mySelector = $("#Industry").val();
    // Check for location property

    if (latitude) {
      // Add a new marker to the cluster group and bind a pop-up
      markers.addLayer(L.marker([latitude, longitude])
        .bindPopup(popText));
    };
  }
}

var industries = allData
  .map(function(row) {
    return row.Industry;
  })
  .sort()
  .filter(function(v, i, arr) {
    // This selects only unique industries:
    // Only return a value if it's the first occurrence or if
    // it's different from the previous entry in the sorted(!) array
    return i === 0 || arr[i - 1] != v;
  });

draw(allData);

d3.select("#selectIndustries")
  // Select all non-disabled options
  // to avoid touching the placeholder one
  .selectAll("option:not([disabled])")
  .data(industries)
  .enter()
  .append("option")
  .attr("value", function(d) {
    return d;
  })
  .text(function(d) {
    return d;
  });

d3.select("#selectIndustries")
  .on("change", function() {
    var selection = this.value;
    var filteredData = allData.filter(function(d) {
      return d.Industry == selection;
    });
    draw(filteredData);
  });
#map {
  height: 400px;
  width: 600px;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin="" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet-src.js"></script>

<div id="map"></div>

<select id="selectIndustries">
  <option disabled selected>Select an option</option>
</select>

【讨论】:

    猜你喜欢
    • 2018-10-04
    • 2019-09-12
    • 1970-01-01
    • 1970-01-01
    • 2017-12-09
    • 2015-08-24
    • 1970-01-01
    • 1970-01-01
    • 2019-12-26
    相关资源
    最近更新 更多