d3.slider 和在时间轴上过滤的日期

d3.slider and dates filtered on a timeline

我有这个 example,其中一些点会随着时间的推移使用滑块生成。我的版本几乎可以正常工作,但我无法理解的是这个问题:

1) 说明热点应该是从头到尾的剧情 2) 显示时间轴上的实际 drage/click 何时结束 3) 当我一次点击到结尾时显示(不拖动)

这个函数过滤了日期,我的理解应该是可以的。该示例和我的版本都使用 underscore.js ,而我的知识非常有限。如果我拖动滑块手柄,它无法正确过滤到最后,是什么导致了这个问题?

var dateParser = d3.time.format("%d.%m.%Y").parse;
var minDate = dateParser("01.01.2015");
var maxDate = dateParser("02.12.2015");
console.log(minDate);
var secondsInDay = 60 * 60 * 24;

d3.select('#slider3').call(d3.slider()
    .axis(true)
    .min(minDate)
    .max(maxDate)
    // .min(function(d){
    //   var date = dateParser(d.properties.date);
    //   return date;
    // })
    // .max(function(d){
    //   var date = dateParser(d.properties.date);
    //   return date;
    // })
    .step(1)
    .on("slide", function(evt, value) {

    newData = site_data.features.filter(function(d){
      //console.log(new Date(value));
      return dateParser(d.properties.date) < new Date(value);
    });
        console.log("New set size ", newData.length);

    displaySites(newData);
  })

我的完整 html 现在看起来像这样

<!DOCTYPE html>
<head>
    <title>D3 Mapping Timeline</title>
<meta charset="utf-8">
<link rel="stylesheet" href="d3.slider.css" />
<style>

path {
  fill: none;
  stroke: #333;
  stroke-width: .5px;
}

.land-boundary {
  stroke-width: 1px;
}

.county-boundary {
  stroke: #ddd;
}

.site {
  opacity: 0.2;
  fill: #9cf;
}

#slider3 {
  margin: 20px 0 10px 20px;
  width: 900px;
}

svg {
  background: #eee;
}

.sphere {
  fill: rgb(92, 136, 255)
}

.land {
  fill: rgb(255, 239, 204)
}

.incident{
  fill:#07f5e7;
  opacity: 0.5;
}

.boundary {
  fill: none;
  stroke: rgb(224, 91, 49);
  stroke-linejoin: round;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

.state {
  fill: #000;
}
.city{
  fill: #de1ae8;
}

.overlay {
  fill: none;
  pointer-events: all;
}
</style>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="d3.slider.js"></script>
</head>
<body>
<div id="slider3"></div>

<script>

var width = 1240,
  height = 720;
var projection = d3.geo.mercator()
    .translate([width / 2, height / 2])
    .scale((width - 1) / 2 / Math.PI);

var zoom = d3.behavior.zoom()
    .scaleExtent([3, 77])
    .on("zoom", zoomed);

var path = d3.geo.path()
    .projection(projection);

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

var g = svg.append("g");
var sites = svg.append("g");

svg.call(zoom)
    .call(zoom.event);

d3.json("countries.topo.json", function(error, world) {
 if (error) throw error;

  g.append("path")
      .datum({type: "Sphere"})
      .attr("class", "sphere")
      .attr("d", path);

  g.append("path")
      .datum(topojson.merge(world, world.objects.countries.geometries))
      .attr("class", "land")
      .attr("d", path);

  g.append("path")
      .datum(topojson.mesh(world, world.objects.countries, function(a, b) { return a !== b; }))
      .attr("class", "boundary")
      .attr("d", path);

//_______________________________________________________________________________________________________________________________________
//________________________________________________________________________________________________________________________________________


  d3.json("germany.topo.json", function(error, ger){
    if (error) throw error;
    var states = topojson.feature(ger, ger.objects.states),
        cities = topojson.feature(ger, ger.objects.cities );

    g.selectAll(".states")
        .data(states.features)
        .enter()
        .append("path")
        .attr("class", "state")
        .attr("class", function(d) { return "state " + d.id; })
        .attr("d", path);
    g.append("path")
        .datum(cities)
        .attr("d", path.pointRadius('0.05'))
        .attr("class", "city");
  });
});

function zoomed() {
  g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
  sites.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}

d3.select(self.frameElement).style("height", height + "px");

d3.json("https://raw.githubusercontent.com/RitterLean/Slider-geojson-testing/master/vorfaelle.json", function(error, data){
    console.log(data.features[1].geometry.coordinates, "sad");
    window.site_data = data;

});


var displaySites = function(data) {
  //console.log(data)
  sites.selectAll(".site")
      .data(data)
      .enter()
      .append("circle")
      .attr("class", "site")
      .attr("cx", function(d) {
        var p = projection(d.geometry.coordinates);
        return p[0];
      })
      .attr("cy", function(d) {
        var p = projection(d.geometry.coordinates);
        return p[1]
      })
      .attr("r", 0)
      .transition().duration(400)
      .attr("r", 0.25);
    //  "".attr""

  sites.selectAll(".site")
        .data(data).exit()//remove the selection which are to be removed from dataset
      .transition().duration(200)
        .attr("r",0)
        .remove();

};


var dateParser = d3.time.format("%d.%m.%Y").parse;
var minDate = dateParser("01.01.2015");
var maxDate = dateParser("02.12.2015");
console.log(minDate);
var secondsInDay = 60 * 60 * 24;

d3.select('#slider3').call(d3.slider()
    .axis(true)
    .min(minDate)
    .max(maxDate)
    // .min(function(d){
    //   var date = dateParser(d.properties.date);
    //   return date;
    // })
    // .max(function(d){
    //   var date = dateParser(d.properties.date);
    //   return date;
    // })
    .step(1)
    .on("slide", function(evt, value) {

    newData = site_data.features.filter(function(d){
      //console.log(new Date(value));
      return dateParser(d.properties.date) < new Date(value);
    });
  console.log("New set size ", newData.length);

    displaySites(newData);
  })
);

</script>
</body>

ann 所有其他文件都可以在我的 repo 上找到,因为我还不知道如何在 Whosebug 上正确共享它。

我有三个想法从哪里开始。也许这与主 html 中滑块功能的最小值和最大值有关,但更改它只会使轴的刻度消失。它也可能是 d3.slider.js 内部的过滤(也许 underscore.js?)。数据只有今年 12 月 2 日的条目,所以一些兴趣点不会因为日期而显示,所以可能与 .min .max 相关的东西?那么为什么它不像它所反对的那样进行过滤呢?

提前致谢

滑块运行良好,过滤正确。

似乎出口识别的数据多于需要删除的数据。因此,更多点不可见。

 sites.selectAll(".site")
        .data(data).exit()//remove the selection which are to be removed from dataset
      .transition().duration(200)
        .attr("r",0)
        .remove();

所以我把 displaySite 函数改成这样:

var displaySites = function(data) {
  //remove all the points 
  sites.selectAll(".site")
      .remove();
  //add all the filtered points    
  sites.selectAll(".site")
      .data(data)
      .enter()
      .append("circle")
      .attr("class", "site")
      .attr("cx", function(d) {
        var p = projection(d.geometry.coordinates);
        return p[0];
      })
      .attr("cy", function(d) {
        var p = projection(d.geometry.coordinates);
        return p[1]
      })
      .attr("r", 0)
      .transition().duration(40)
      .attr("r", 0.23);
};

工作代码here

另一种方式:

在数据中传递用于唯一标识对象的唯一标识符。 下面我假设每个点都有一个独特的描述请相应地更改它

var displaySites = function(data) {
  var sitedata = sites.selectAll(".site")
      .data(data, function(d){return d.properties.description});//uniquely identify each dataset point

  sitedata
      .enter()
      .append("circle")
      .attr("class", "site")
      .attr("cx", function(d) {
        var p = projection(d.geometry.coordinates);
        return p[0];
      })
      .attr("cy", function(d) {
        var p = projection(d.geometry.coordinates);
        return p[1]
      })
      .attr("r", 0)
      .transition().duration(40)
      .attr("r", 0.23);

    sitedata.exit()//remove the selection which are to be removed from dataset
      .transition().duration(200)
        .attr("r",0)
        .remove();

};

工作代码here

希望对您有所帮助