2016-12-27 87 views
0

我創建了日曆熱圖,但問題是落入制動器「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

你爲什麼要迭代'breaks.length + 1':breaks[0]breaks[1]之間breaks[0]和價值觀下的價值觀? – epascarello

+0

@epascarello:感謝您的注意。我改成了'i = 0;我 Dinosaurius

回答

0

您的顏色選擇代碼的尺寸可能會縮小一些,而使用d3比例尺來選擇顏色也會使其更清潔。但是,最終,你的問題就出在這裏:

  if (d.value>breaks.length-1){ 
       return colours[breaks.length] 
      } 

這部分代碼時,色彩也尚未歸還只叫,那就是,對於那些雖然我不知道爲什麼會比4550更大的價值在這個代碼塊中的if語句是需要的,你的數組breakscolours是相同的長度。基本上你要返回array[array.length],因爲數組是零索引的,所以不會返回值。您可能想要返回colours[colours.length-1],因爲您需要最後指定的顏色。


編輯:另外,如果您分配了那些低於最低的休息顏色(它似乎你做的)和上面的最高,你將需要比間斷值多一個顏色。例如:一箇中斷標度在中斷之上/之下有兩種顏色。但是,你可能有故意應用於colours[0]既:

  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]; 
       } 
      }