[英]Filtering data with radio button (animated map)
I have animated slider map that takes lat/long data and displays it based on when a type of building has been erected. 我有一个动画的滑块地图,该地图可以获取经/纬度数据,并根据何时搭建的建筑物类型进行显示。 Currently, I am only able to display data for skyscrapers, however I would like each of the buttons to filter data for "residential" and "hospitals" as well.
目前,我只能显示摩天大楼的数据,但是我希望每个按钮也可以过滤“住宅”和“医院”的数据。
d.skyscrp is what is pulling the date data from data5001.txt, and then moment() is parsing the data as information to be read by the browser. d.skyscrp是从data5001.txt中提取日期数据,然后moment()将数据解析为要由浏览器读取的信息。 I need to access d.residential and d.hospitals as well.
我还需要访问d.residential和d.hospitals。 So far I am able to load the data, but do not know how to make the buttons filter out what i need.
到目前为止,我已经能够加载数据,但是不知道如何使按钮过滤掉我所需的内容。
I have a full working example here on bl.ocks with all the code available. 我在bl.ocks上有一个完整的工作示例 ,其中提供了所有可用代码。
Plunker of code located here 位于此处的代码笨拙
Index.html below as well for reference: 下面还有Index.html供参考:
<!DOCTYPE html>
<head>
<title>Map</title>
<meta charset="utf-8">
<link rel="stylesheet" href="d3.slider.css"/>
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Inconsolata" rel="stylesheet">
<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/moment.js/2.10.3/moment.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="update">
<div id="agegrp" class="buttons">
<div class="button current" data-val="1" onclick = "updateData()" id = "option" name="updateButton"
type="button" value = "Update">Button1</div>
<div class="button" data-val="2">Button2</div>
<div class="button" data-val="3">Button3</div>
<div class="button" data-val="4" style="margin-right:0">Button4</div>
<div class="clr"></div>
</div>
</div><!-- @end #update -->
<div id="title">
</div>
<div id="subtitle">
</div>
<div id="axis1985">
<h8></h8>
</div>
<div id="axis1990">
<h8>1990</h8>
</div>
<div id="axis1995">
<h8>1995</h8>
</div>
<div id="axis2000">
<h8>2000</h8>
</div>
<div id="axis2005">
<h8>2005</h8>
</div>
<div id="axis2010">
<h8>2010</h8>
</div>
<div id="axis2015">
<h8>2015</h8>
</div>
<div id="slider3">
</div>
<div id="slidertextplaceholder"></div>
<div id="slidertext"></div>
<div id="option">
<input name="updateButton"
type="button"
value="Update"
onclick="updateData()" />
</div>
<script>
var width = 960,
height = 850;
var mapPath = "usa.json";
// Define the div for the tooltip
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var projection = d3.geo.albersUsa()
.scale(1080)
.translate([width / 2, height / 2]);
var path = d3.geo.path()
.projection(projection);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
d3.json(mapPath, function(error, us) {
if (error) return console.error(error);
svg.append("path")
.datum(topojson.feature(us, us.objects.land))
.attr("d", path)
.attr("class", "land-boundary");
svg.append("path")
.datum(topojson.mesh(us, us.objects.counties, function(a, b) { return a !== b && (a.id / 1000 | 0) === (b.id / 1000 | 0); }))
.attr("d", path)
.attr("class", "county-boundary");
svg.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
.attr("d", path)
.attr("class", "state-boundary");
d3.tsv("data5001.txt")
.row(function(d) {
return {
permalink: d.permalink,
lat: parseFloat(d.lat),
lng: parseFloat(d.lon),
state: d.state,
fullAddress: d.fullAddress,
buildingName: d.buildingName,
skyscrp: moment(d.skyscrp,"YYYY-MM-DD HH:mm"),
residential: moment(d.residential,"YYYY-MM-DD HH:mm"),
hospital: moment(d.hospital,"YYYY-MM-DD HH:mm")
};
})
.get(function(err, rows) {
if (err) return console.error(err);
window.site_data = rows;
});
});
//display the sites using "permalink"
var displaySites = function(data) {
var sites = svg.selectAll(".site")
.data(data, function(d) {
return d.permalink;
});
sites.enter().append("circle")
.attr("class", "site")
.attr("cx", function(d) {
return projection([d.lng, d.lat])[0];
})
.attr("cy", function(d) {
return projection([d.lng, d.lat])[1];
})
.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div.html("building Name:" + "<br>" + d.buildingName + "<br>" + "<br>" + "Address:" + "<br>" + d.fullAddress + "<br>")
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(200)
.style("opacity", 0);
})
.attr("r", 1)
.transition().duration(800)
.attr("r", 7);
sites.exit()
.transition().duration(200)
.attr("r",0)
.remove();
};
var minDateYear = moment('1985-12-19', "YYYY-MM-DD HH:mm");
var maxDateYear = moment('2017-09-29', "YYYY-MM-DD HH:mm");
var secondsInDay = 60 * 60 * 24;
d3.select('#slider3').call(d3.slider()
//.axis(true).min("1986").max("2017")
.axis(false).min(minDateYear).max(maxDateYear)
.on("slide", function(evt, value) {
var newData = _(site_data).filter( function(site) {
return site.skyscrp < value;
})
//console.log("New set size ", newData.length);
//console.log("svg value ", newData);
document.getElementById("slidertext").innerHTML = "Achieved Goals: " + newData.length;
displaySites(newData);
})
);
document.getElementById("slidertextplaceholder").innerHTML = "Achieved Goals: " + " ____ " + "buildings";
</script>
</body>
You just need to pull your filter out into shared code. 您只需要将过滤器放入共享代码即可。
Here is how I would go about it: 这是我的处理方法:
// First, a variable to keep the year we're filtering on.
var yearMin = 0;
// Another one to keep track of the building type we're filtering on.
var buildingType = 'skyscrp';
// Shared function
function filterData() {
var newData = _(site_data).filter(function(site) {
return site[buildingType] < minYear;
});
displaySites(newData);
document.getElementById("slidertext").innerHTML =
"Achieved Goals: " + newData.length;
}
I've made a few assumptions, but the basic idea is I filter on year and also on building type in the same statement. 我做了一些假设,但基本思路是我在同一条语句中根据年份和建筑类型进行过滤。
So each of the buttons will set buildingType
to an appropriate value. 因此,每个按钮都会将
buildingType
设置为适当的值。 After setting the value of buildingType
, they call filterData();
设置
buildingType
的值后,他们调用filterData();
. 。
function buttonClick(filterField) {
if (filterField !== undefined) {
console.info('Changing building filter to', filterField);
buildingType = filterField;
}
console.info('Applying filter');
filterData();
}
Then, for the slider, you modify the code like this: 然后,对于滑块,您可以如下修改代码:
d3.select('#slider3').call(d3.slider()
.axis(false).min(minDateYear).max(maxDateYear)
.on("slide", function(evt, value) {
console.info('Changing year filter to', value);
minYear = value;
filterData();
})
);
Edit 编辑
Looking at the data, it seemed to me more likely that you want to filter on a different field, depending on the selected button. 查看数据,在我看来,您更有可能希望根据所选按钮在其他字段上进行过滤。 For example, right now you're filtering on
skyscrp
, but there are also hospital
and residential
fields. 例如,现在您正在对
skyscrp
过滤,但也有hospital
和residential
。
So, using the same strategy as before, I just altered the filterData
function, yielding a working plunkr . 因此,使用与以前相同的策略,我只是更改了
filterData
函数,产生了一个有效的plunkr 。
These are the changes I made, reflected in the code above: 这些是我所做的更改,反映在上面的代码中:
onclick
handler to your first three buttons. onclick
处理程序。 Each button sends through one of the three field names 'skyscrp', 'hospital' or 'residential'. buttonClick
function which, as explained before, simply sets the filter and calls filterData()
. buttonClick
函数,该函数只需设置过滤器并调用filterData()
。 But instead of a number representing the building type, I now use the actual field name in your data. filterData
to now use that field for the comparison. filterData
,现在使用该字段进行比较。 Edit 2 编辑2
Updating the label now happens within filterData
, which gives a more consistent experience. 现在,更新标签发生在
filterData
内,从而提供了更加一致的体验。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.