我已经创建了一个日历热图,但问题是刹车的数据超过4500"标记为黑色而不是指示的颜色#3d3768
。看起来这个类别找不到颜色。为什么呢?
<!DOCTYPE html>
<meta charset="utf-8">
<head>
<title>Data Calendar</title>
<style>
.month {
fill: none;
stroke: #000;
stroke-width: 2px;
}
.day {
fill: #fff;
stroke: #ccc;
}
text {
font-family:sans-serif;
font-size:1.5em;
}
.dayLabel {
fill:#aaa;
font-size:0.8em;
}
.monthLabel {
text-anchor:middle;
font-size:0.8em;
fill:#aaa;
}
.yearLabel {
fill:#aaa;
font-size:1.2em;
}
.key {font-size:0.5em;}
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
<script>
var breaks=[1500,2500,3500,4500,4550];
var colours=["#e2dff1","#b7b1dd","#8b82c8","#584f95","#3d3768"];
//general layout information
var cellSize = 17;
var xOffset=20;
var yOffset=60;
var calY=50;//offset of calendar in each group
var calX=25;
var width = 960;
var height = 163;
var parseDate = d3.time.format("%d/%m/%y").parse;
format = d3.time.format("%d-%m-%Y");
toolDate = d3.time.format("%d/%b/%y");
d3.csv("data.csv", function(error, data) {
//set up an array of all the dates in the data which we need to work out the range of the data
var dates = new Array();
var values = new Array();
//parse the data
data.forEach(function(d) {
dates.push(parseDate(d.date));
values.push(d.value);
d.date=parseDate(d.date);
d.value=d.value;
d.year=d.date.getFullYear();//extract the year from the data
});
var yearlyData = d3.nest()
.key(function(d){return d.year;})
.entries(data);
var svg = d3.select("body").append("svg")
.attr("width","90%")
.attr("viewBox","0 0 "+(xOffset+width)+" 540")
//title
svg.append("text")
.attr("x",xOffset)
.attr("y",20)
.text(title);
//create an SVG group for each year
var cals = svg.selectAll("g")
.data(yearlyData)
.enter()
.append("g")
.attr("id",function(d){
return d.key;
})
.attr("transform",function(d,i){
return "translate(0,"+(yOffset+(i*(height+calY)))+")";
})
var labels = cals.append("text")
.attr("class","yearLabel")
.attr("x",xOffset)
.attr("y",15)
.text(function(d){return d.key});
//create a daily rectangle for each year
var rects = cals.append("g")
.attr("id","alldays")
.selectAll(".day")
.data(function(d) { return d3.time.days(new Date(parseInt(d.key), 0, 1), new Date(parseInt(d.key) + 1, 0, 1)); })
.enter().append("rect")
.attr("id",function(d) {
return "_"+format(d);
//return toolDate(d.date)+":\n"+d.value+" dead or missing";
})
.attr("class", "day")
.attr("width", cellSize)
.attr("height", cellSize)
.attr("x", function(d) {
return xOffset+calX+(d3.time.weekOfYear(d) * cellSize);
})
.attr("y", function(d) { return calY+(d.getDay() * cellSize); })
.datum(format);
//create day labels
var days = ['Su','Mo','Tu','We','Th','Fr','Sa'];
var dayLabels=cals.append("g").attr("id","dayLabels")
days.forEach(function(d,i) {
dayLabels.append("text")
.attr("class","dayLabel")
.attr("x",xOffset)
.attr("y",function(d) { return calY+(i * cellSize); })
.attr("dy","0.9em")
.text(d);
})
//let's draw the data on
var dataRects = cals.append("g")
.attr("id","dataDays")
.selectAll(".dataday")
.data(function(d){
return d.values;
})
.enter()
.append("rect")
.attr("id",function(d) {
return format(d.date)+":"+d.value;
})
.attr("stroke","#ccc")
.attr("width",cellSize)
.attr("height",cellSize)
.attr("x", function(d){return xOffset+calX+(d3.time.weekOfYear(d.date) * cellSize);})
.attr("y", function(d) { return calY+(d.date.getDay() * cellSize); })
.attr("fill", function(d) {
if (d.value<breaks[0]) {
return colours[0];
}
for (i=0;i<breaks.length+1;i++){
if (d.value>=breaks[i]&&d.value<breaks[i+1]){
return colours[i];
}
}
if (d.value>breaks.length-1){
return colours[breaks.length]
}
})
//append a title element to give basic mouseover info
dataRects.append("title")
.text(function(d) { return toolDate(d.date)+":\n"+d.value+units; });
//add montly outlines for calendar
cals.append("g")
.attr("id","monthOutlines")
.selectAll(".month")
.data(function(d) {
return d3.time.months(new Date(parseInt(d.key), 0, 1),
new Date(parseInt(d.key) + 1, 0, 1));
})
.enter().append("path")
.attr("class", "month")
.attr("transform","translate("+(xOffset+calX)+","+calY+")")
.attr("d", monthPath);
//retreive the bounding boxes of the outlines
var BB = new Array();
var mp = document.getElementById("monthOutlines").childNodes;
for (var i=0;i<mp.length;i++){
BB.push(mp[i].getBBox());
}
var monthX = new Array();
BB.forEach(function(d,i){
boxCentre = d.width/2;
monthX.push(xOffset+calX+d.x+boxCentre);
})
//create centred month labels around the bounding box of each month path
//create day labels
var months = ['JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC'];
var monthLabels=cals.append("g").attr("id","monthLabels")
months.forEach(function(d,i) {
monthLabels.append("text")
.attr("class","monthLabel")
.attr("x",monthX[i])
.attr("y",calY/1.2)
.text(d);
})
//create key
var key = svg.append("g")
.attr("id","key")
.attr("class","key")
.attr("transform",function(d){
return "translate("+xOffset+","+(yOffset-(cellSize*1.5))+")";
});
key.selectAll("rect")
.data(colours)
.enter()
.append("rect")
.attr("width",cellSize)
.attr("height",cellSize)
.attr("x",function(d,i){
return i*130;
})
.attr("fill",function(d){
return d;
});
key.selectAll("text")
.data(colours)
.enter()
.append("text")
.attr("x",function(d,i){
return cellSize+5+(i*130);
})
.attr("y","1em")
.text(function(d,i){
if (i<colours.length-1){
return "up to "+breaks[i] + "%";
} else {
return "over "+breaks[i-1] + "%";
}
});
});//end data load
//pure Bostock - compute and return monthly path data for any year
function monthPath(t0) {
var t1 = new Date(t0.getFullYear(), t0.getMonth() + 1, 0),
d0 = t0.getDay(), w0 = d3.time.weekOfYear(t0),
d1 = t1.getDay(), w1 = d3.time.weekOfYear(t1);
return "M" + (w0 + 1) * cellSize + "," + d0 * cellSize
+ "H" + w0 * cellSize + "V" + 7 * cellSize
+ "H" + w1 * cellSize + "V" + (d1 + 1) * cellSize
+ "H" + (w1 + 1) * cellSize + "V" + 0
+ "H" + (w0 + 1) * cellSize + "Z";
}
</script>
</body>
</html>
答案 0 :(得分:0)
您的颜色选择代码的大小可能会有所减少,使用d3刻度来选择您的颜色也会使其更加清晰。但是,最终,你的问题在于:
if (d.value>breaks.length-1){
return colours[breaks.length]
}
仅在尚未返回颜色时调用此部分代码,即对于那些大于4550的值。当我不确定为什么需要此代码块中的if语句时,您的数组{ {1}}和breaks
的长度相同。本质上,您将返回colours
,由于数组为零索引,因此不会返回值。您可能希望返回array[array.length]
,因为您想要最后指定的颜色。
编辑:此外,如果为低于最低休息时间(您出现的那些)和高于最低休息时间的那些分配颜色,则需要多一个颜色而不是中断值。例如:一个中断刻度有两种颜色,用于休息时间上方/下方。但是,您可能故意将colours[colours.length-1]
同时应用于colours[0]
下的值和breaks[0]
与breaks[0]
之间的值:
breaks[1]