我有一个动画滑块地图,它可以获取经纬度数据,并根据一种建筑类型的建立时间来显示它。目前,我只能显示摩天大楼的数据,但是我希望每个按钮都能过滤“住宅”和“医院”的数据。
d.skyscrp从data5001.txt中提取日期数据,然后moment()将数据解析为浏览器要读取的信息。我还需要访问d.residential和d.hospitals。到目前为止,我可以加载数据,但不知道如何让按钮过滤出我需要的内容。
我在bl.ocks上有一个full working example,里面有所有可用的代码。
下面的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>
发布于 2018-06-10 21:19:29
您只需将您的过滤器拉出到共享代码中。
下面是我的做法:
// 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;
}
我做了一些假设,但基本思想是我在同一语句中根据年份和建筑类型进行过滤。
因此,每个按钮都会将buildingType
设置为适当的值。在设置了buildingType
的值之后,它们调用filterData();
。
function buttonClick(filterField) {
if (filterField !== undefined) {
console.info('Changing building filter to', filterField);
buildingType = filterField;
}
console.info('Applying filter');
filterData();
}
然后,对于滑块,您可以像这样修改代码:
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();
})
);
编辑
从数据来看,在我看来,您更有可能想要根据所选的按钮来筛选不同的字段。例如,现在您正在过滤skyscrp
,但也有hospital
和residential
字段。
因此,使用与前面相同的策略,我只是修改了filterData
函数,生成了一个有效的plunkr。
以下是我所做的更改,反映在上面的代码中:
onclick
处理程序。每个按钮通过三个字段名称之一发送:“skyscrp”、“医院”或“住宅”。我还更改了它们的标题以匹配它们应用的滤镜,但您需要做一些额外的工作来更新屏幕上的样式,以显示哪个滤镜是活动的-我不认为这属于您的question.buttonClick
函数的作用域,如前所述,该函数只是设置滤镜并调用filterData()
。但是,我现在使用的不是表示建筑类型的数字,而是data.filterData
中的实际字段名称,以便使用该字段进行比较。编辑2
现在可以在filterData
中更新标签,这提供了更一致的体验。
https://stackoverflow.com/questions/50761515
复制相似问题