2015-12-28 2 views
3

У меня есть это example, где некоторые моменты появляются со временем с помощью слайдера. Моя версия почти работает, но то, что я не могу получить мою голову вокруг этой проблемы: enter image description hered3.slider и даты, отфильтрованные по временной шкале

1) Показывает горячий это должны быть нанесены с начала до конца 2) Показывает, когда актуально Драг/нажмите на временной шкале до конца 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) { 
 
\t 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); 
 
    }); 
 
\t \t console.log("New set size ", newData.length); 
 

 
    displaySites(newData); 
 
    }) 
 
); 
 

 
</script> 
 
</body>

апп все остальные файлы можно найти на моем repo, потому что я еще не знаю, как разделить его правильно на stackoverflow.

У меня есть три идеи, с чего начать. Возможно, это связано с минимальным и максимальным функциями слайдера в главном html, но изменение его просто заставило галочки оси исчезнуть. Это также может быть что-то с фильтрацией внутри d3.slider.js (возможно, underscore.js?). Данные имеют только записи во 2-ое декабря этого года, поэтому некоторые точки интереса не будут отображаться из-за даты, поэтому возможно что-то связанное с .min .max? Так почему же он не фильтрует, как это было сопротивление?

Спасибо заранее

ответ

1

Слайдер прекрасно работает и отфильтровывая его правильно.

Кажется, что выход идентифицирует больше данных, чем нужно удалить. Таким образом, больше очков не видно.

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

Надеется, что это помогает

+1

Вы сударь лучший – basedian

Смежные вопросы