使用jQuery过滤D3.js地图?

时间:2018-12-04 16:20:47

标签: javascript jquery json d3.js leaflet

我有一个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();
  }
});

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

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

项目外观示例: enter image description here

1 个答案:

答案 0 :(得分:0)

我一直在寻找的答案包含在以下代码中(特别是^=):

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
}

希望这对某人有帮助。