我有一张D3地图应该按照它们在一定范围内的范围填充美国各县。我没有D3确定我的范围,数据是0,.5,1和10作为分位数。
我遇到的问题是各县没有填充适当的颜色,因为它们在范围内。我知道这是因为我可以通过工具提示看到这些值。它几乎就像是另一个被切入分位数的值。
有一个复杂的问题是我有一个下拉列表来选择一个额外的变量来填充地图(这些变量的分位数相同)
以下是我认为我的问题所在,初始代码,updateMap函数或图例本身。谢谢你的任何建议。
var width = 800,
height = 500;
var statById = d3.map();
var quantile = d3.scale.quantile()
.domain([0,.5,1,10])
.range(['white','blue','red', 'green']);
function updateMap(key){
quantile.domain(counties.map(function(d){return d[key];}));
countyShapes
.transition().duration(1000).ease(d3.ease('linear'))
.attr("fill", function(d) {
if (statById.get(d.id)){
if(statById.get(d.id)[key] == 0){
return 'white';
}
else{
return quantile(statById.get(d.id)[key]);
}
}
else{
errorArray.push(d.id);
return "white";
}});
}
var legend = svg.selectAll('g.legendEntry')
.data(quantile.range().reverse())
.enter()
.append('g').attr('class', 'legendEntry');
legend
.append('rect')
.attr("x", width - 780)
.attr("y", function(d, i) {
return i * 20;
})
.attr("width", 10)
.attr("height", 10)
.style("stroke", "black")
.style("stroke-width", 1)
.style("fill", function(quantile){return quantile;});
//the data objects are the fill colors
legend
.append('text')
.attr("x", width - 760) //leave 5 pixel space after the <rect>
.attr("y", function(d, i) {
return i * 20;
})
.attr("dy", "0.8em") //place text one line *below* the x,y point
.text(function(d,i) {
var extent = quantile.invertExtent(d);
//extent will be a two-element array, format it however you want:
var format = d3.format("0.2f");
return format(+extent[0]) + " - " + format(+extent[1]);
});
以下是渲染地图的整个脚本:
<script>
var width = 800,
height = 500;
var statById = d3.map();
var quantile = d3.scale.quantile()
.domain([0,.5,1,10])
.range(['white','blue','red', 'green']);
var path = d3.geo.path();
var svg = d3.select("#map")
.attr("width", width)
.attr("height", height)
.append('svg:g')
.call(d3.behavior.zoom().on("zoom", redraw))
.append('svg:g');
svg.attr("transform", "scale( " + .9 + ")");
function redraw() {
console.log("here", d3.event.translate, d3.event.scale);
svg.attr("transform",
"translate(" + d3.event.translate + ")"
+ " scale(" + d3.event.scale + ")");
}
d3.select("#selectPer")
.on("change", function(){menuChange();});
d3.select("#selectType")
.on("change", function(){menuChange();});
var tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 1e-6)
.style("background", "rgba(250,250,250,.7)");
tooltip.append("span").attr("id", "countyName")
queue()
.defer(d3.json, "us.json")
.defer(d3.csv, "mvpfinal020715.csv")
.defer(d3.json, "countyPop.json")
.await(ready);
errorArray = [];
var counties;
var countyPop;
function ready(error, us, countiesJSON, countyPopJSON) {
counties = countiesJSON;
countyPop = countyPopJSON;
counties.forEach(function(d){
try{
d.lq_11 = +d['lq_11'];
d.lq_21 = +d['lq_21'];
d.lq_22 = +d['lq_22'];
d.lq_23 = +d['lq_23'];
d.lq_42 = +d['lq_42'];
d.lq_51 = +d['lq_51'];
d.lq_52 = +d['lq_52'];
d.lq_53 = +d['lq_53'];
d.lq_55 = +d['lq_55'];
d.lq_56 = +d['lq_56'];
d.lq_61 = +d['lq_61'];
d.lq_62 = +d['lq_62'];
d.lq_71 = +d['lq_71'];
d.lq_72 = +d['lq_72'];
d.lq_81 = +d['lq_81'];
d.lq_92 = +d['lq_92'];
statById.set(+d.fips, d);
if (isNaN('white')){
}
}
catch(e){
//remove double lines of csv
}
});
quantile.domain(counties.map(function(d){return d.subPerCap;}));
countyShapes = svg.append("g")
.attr("class", "counties")
.selectAll("path")
.data(topojson.feature(us, us.objects.counties).features)
.enter().append("path")
countyShapes
.attr("fill", "rgb(200,200,200)")
.attr("d", path)
.on("mouseover", function(d){
d3.select(this)
.attr("stroke", "red")
.attr("stroke-width", 1)
tooltip
.style("left", (d3.event.pageX + 5) + "px")
.style("top", (d3.event.pageY - 5) + "px")
.transition().duration(300)
.style("opacity", 1)
.style("display", "block")
updateDetails(statById.get(d.id));
})
.on("mouseout", function(d){
d3.select(this)
.attr("stroke", "")
.attr("stroke-width", .2)
tooltip.transition().duration(700).style("opacity", 0);
});
svg.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
.attr("class", "states")
.attr("d", path);
menuChange();
}
var printDetails = [
{'var': 'fips', 'print': 'FIPS'},
{'var': 'lq_21', 'print': 'Mining'},
{'var': 'lq_23', 'print': 'Construction'},
{'var': 'lq_51', 'print': 'Information'},
{'var': 'lq_52', 'print': 'Finance'},
{'var': 'No Criminal Conviction Return', 'print': 'Paperwork Returns'},
{'var': 'none', 'print': ''},
{'var': 'population', 'print': 'Population'},
{'var': 'Activation Date', 'print': 'Start Date'}];
function updateDetails(county){
tooltip.selectAll("div").remove();
tooltip.selectAll("div").data(printDetails).enter()
.append("div")
.append('span')
.text(function(d){return (d.print.length > 0) ? d.print + ": " : " - ";})
.attr("class", "boldDetail")
.insert('span')
.text(function(d){
if (d.var != 'none'){
return (""+county[d.var]).indexOf('/') == -1 ? totalFormat(county[d.var]) : county[d.var];
}})
.attr("class", "normalDetail");
d3.select("#countyName").text(county.County);
}
var totalFormat = d3.format(",");
function menuChange(){
var selectPer = document.getElementById('selectPer');
selectPerValue = selectPer.options[selectPer.selectedIndex].value;
var selectType = document.getElementById('selectType');
selectTypeValue = selectType.options[selectType.selectedIndex].value;
var keyName = selectTypeValue + (selectPerValue == 'PerCap' ? 'PerCap' : '');
console.log(keyName);
updateMap(keyName);
console.log(d3.sum(counties, function(d){return d[selectTypeValue];}));
var num = d3.sum(counties, function(d){return d[selectTypeValue];});
d3.select("#magicNum")
.text(selectPerValue == 'PerCap' ? d3.round(num*10000/313000000, 3) + " per 100,000" : totalFormat(num));
}
function updateMap(key){
quantile.domain(counties.map(function(d){return d[key];}));
countyShapes
.transition().duration(1000).ease(d3.ease('linear'))
.attr("fill", function(d) {
if (statById.get(d.id)){
if(statById.get(d.id)[key] == 0){
return 'white';
}
else{
return quantile(statById.get(d.id)[key]);
}
}
else{
errorArray.push(d.id);
return "white";
}});
}
var legend = svg.selectAll('g.legendEntry')
.data(quantile.range().reverse())
.enter()
.append('g').attr('class', 'legendEntry');
legend
.append('rect')
.attr("x", width - 780)
.attr("y", function(d, i) {
return i * 20;
})
.attr("width", 10)
.attr("height", 10)
.style("stroke", "black")
.style("stroke-width", 1)
.style("fill", function(quantile){return quantile;});
//the data objects are the fill colors
legend
.append('text')
.attr("x", width - 760) //leave 5 pixel space after the <rect>
.attr("y", function(d, i) {
return i * 20;
})
.attr("dy", "0.8em") //place text one line *below* the x,y point
.text(function(d,i) {
var extent = quantile.invertExtent(d);
//extent will be a two-element array, format it however you want:
var format = d3.format("0.2f");
return format(+extent[0]) + " - " + format(+extent[1]);
});
</script>