【问题标题】:Filtering a D3.js map using jquery?使用 jquery 过滤 D3.js 地图?
【发布时间】:2018-12-04 16:20:47
【问题描述】:

我有一个 D3.js 项目,我正在使用他们的纬度和经度在地图上绘制餐厅。目前我有一个脚本,它在 JSON 文件中提取数据和过滤对象。我正在尝试按 1-5 的星级过滤(显示/隐藏)餐厅。

我的问题是,某些餐厅的评分为 4.5 或 3.5,而这些餐厅在单击复选框后并未显示在地图上。是否可以在一个复选框中包含多个值?如何将 4 分与 4.5 分结合起来?


我正在使用的 JSON 数据片段:

"categories": [
  {
    "alias": "korean",
    "title": "Korean"
  },
  {
     "alias": "bbq",
     "title": "Barbeque"
  }
],
"rating": 3.5,
"coordinates": {
  "latitude": 38.994812,
  "longitude": -76.931832
},
"transactions": [
  "pickup"
], 

HTML:

<h2>Star Rating</h2>
<div id="star-filter">
  <div class="boxes">
    <input class="star" type="checkbox" value="5" id="s5" name="check" />
    <label for="s5"><img src="img/5star.png"></label>
  </div>
  <div class="boxes">
    <input class="star" type="checkbox" value="4" data-valuetwo="4.5" id="s4" name="check" />
    <label for="s4"><img src="img/4star.png"></label>
  </div>
  <div class="boxes">
    <input class="star" type="checkbox" value="3" id="s3" name="check" />
    <label for="s3"><img src="img/3star.png"></label>
  </div>
  <div class="boxes">
    <input class="star" type="checkbox" value="2" id="s2" name="check" />
    <label for="s2"><img src="img/2star.png"></label>
  </div>
  <div class="boxes">
    <input class="star" type="checkbox" value="1" id="s1" name="check" />
    <label for="s1"><img src="img/star.png"></label>
  </div>
</div>

如您所见,我尝试在第二个复选框上使用第二个值 (data-valuetwo="4.5"),但没有成功。

D3.js:

var map = L.map('map').setView([38.9936, -76.9538], 14);
      mapLink = 
          '<a href="http://openstreetmap.org">OpenStreetMap</a>';
      L.tileLayer(
          'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
          attribution: '&copy; ' + mapLink + ' Contributors',
          maxZoom: 18,
          }).addTo(map);

/* Initialize the SVG layer */
map._initPathRoot()    

// We simply pick up the SVG from the map object
var svg = d3.select("#map").select("svg"),
g = svg.append("g");

var svg = d3.select("body")
  .append("svg")
  .attr("width",300)
  .attr("height",300);

var tooltip = d3.select("body").append("div")
  .attr("class", "tooltip")
  .style('opacity', 0)
  .style('position', 'absolute')
  .style('padding', '0 10px');


d3.json("../data/yelp-fusion.json", function(collection) {
  // Add a LatLng object to each item in the dataset 
  collection.businesses.forEach(function(d) {
    d.LatLng = new L.LatLng(d.coordinates.latitude,
                d.coordinates.longitude)
  })

  var feature = g.selectAll("circle")
    .data(collection.businesses)
    .enter().append("circle")
    .style("stroke", "blue")  
    .style("opacity", .6) 
    .style("fill", "blue")
    .attr("r", 10)

    // Adding classes directly from the JSON data to the svg circles to hopefully filter later
    .attr("data-id", function(d){return d.id;})
    .attr("data-star", function(d){return d.rating;})
    .attr("data-review", function(d){return d.review_count;})
    .attr("data-cat", function(d){return d.categories[0].title;})

    .on("mouseover", function(d) {
      var html  = d.name + "<br><hr>" + "Star Rating: " + d.rating + "<br>" + "Total Review: " + d.review_count;
      tooltip.html(html)
        .style('background', '#fff')
        .style("left", (d3.event.pageX + 25) + "px")
        .style("top", (d3.event.pageY - 30) + "px")
      .transition()
        .duration(200) // ms
        .style("opacity", .9) // started as 0!
    })
    .on("mouseout",function(d) {
       tooltip.transition()
        .duration(300) // ms
        .style("opacity", 0); // don't care about position!
    })

  map.on("viewreset", update);
  update();

  function update() {
    feature.attr("transform", 
    function(d) { 
      return "translate("+ 
        map.latLngToLayerPoint(d.LatLng).x +","+ 
        map.latLngToLayerPoint(d.LatLng).y +")";
      }
    )
  }
})  

JS:

$('#star-filter').delegate('input[type=checkbox]', 'change', function() {
  $('input.star').not(this).prop('checked', false);  
  var $list = $('.leaflet-zoom-animated > g > circle'),
  $checked = $('input:checked');  
  if ($checked.length) {              
    var selector = '';
    $($checked).each(function(index, element){                            
      selector += "[data-star~='" + element.value + "']";                            
    });                        
    $list.hide();                        
    $('.leaflet-zoom-animated > g > circle').filter(selector).show();        
  }
  else {
    $list.show();
  }
});

如果有帮助,我可以尝试发布完整的项目。

提前致谢。请询问我是否可以提供任何信息,或者我是否遗漏了任何可以提供帮助的信息。

项目外观示例:

【问题讨论】:

  • 你不能在绘图之前过滤你的数据集,而不是把它们全部绘制出来,然后在事后用 jQuery 过滤 DOM 吗?
  • 不确定,想法是绘制所有 svg 圆圈,然后根据我刚刚添加的图像中显示的侧边栏中的参数进行过滤。
  • 您应该过滤绑定的数据,然后更新您的选择。您需要提供您的 d3 代码
  • @JulienLeray 嗨,你能详细说明我如何过滤绑定数据吗?我添加了我的 D3.js 代码

标签: javascript jquery json d3.js leaflet


【解决方案1】:

我正在寻找的答案包含在这段代码中(特别是^=):

function createFilter(type) { // Helper function
  var filter = [];
    $("#" + type + '-filter input:checked').each(function(index, element) {
      filter.push("[data-" + type + "^='" + element.value + "']"); // Use ^= to 
      match the start of the actual value
    });
  return filter.join(",") || "*"; // Asterisk means: no filter at all
}

希望这对某人有所帮助。

【讨论】:

    猜你喜欢
    • 2013-09-05
    • 1970-01-01
    • 1970-01-01
    • 2021-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-24
    相关资源
    最近更新 更多