2014-02-27 98 views
0

任何人可以幫助我轉換d3.js日曆視圖實現,它看起來像一個在這裏描述(周爲列):D3 Calendar View using Associative Arrayd3.js日曆視圖周

到更多的東西像這樣(周爲行):http://kamisama.github.io/cal-heatmap/v2/(看月份>天(水平)部分)

我已經去玩了斧頭,但無濟於事。

任何幫助將不勝感激。

我當前的代碼如下所示:

raApp.directive('heatMapYear', function() { 
var width = 1200, 
    height = 150, 
    cellSize = 17; // cell size 

var day = d3.time.format("%w"), 
    week = d3.time.format("%U"), 
    month = d3.time.format("%m"), 
    monthName = d3.time.format("%b"), 
    format = d3.time.format("%Y-%m-%d"); 

var color = d3.scale.quantize() 
    .domain([1, 5]) 
    .range(d3.range(5).map(function(d) { return "rank" + d; })); 

return { 
    restrict: 'A' 
    , replace: false 
    , scope: { 
     chartData: '=' 
     , dateField: '=' 
    } 
    , link: function (scope, element, attrs) { 
     scope.$watch('chartData', function(newData, oldData) { 
      d3.select(element[0]).selectAll('*').remove(); 

      if (newData != undefined) { 
       var svg = d3.select(element[0]).selectAll("svg") 
        .data(function() { 
         var years = []; 

         for (var i = 0; i < newData.length; i++) { 
          var date = newData[i][scope.dateField]; 
          var year = parseInt(date.substring(0, 4)); 

          if (years.indexOf(year) == -1) { 
           years.push(year); 
          } 
         } 

         return years; 
        }) 
        .enter().append("svg") 
        .attr("width", width) 
        .attr("height", height) 
        .attr("class", "heatClass") 
        .append("g") 
        .attr("transform", "translate(" + 50 + "," + (height - cellSize * 7 - 1) + ")"); 

       svg.append("text") 
        .attr("transform", "translate(-30," + cellSize * 3.5 + ")rotate(-90)") 
        .style("text-anchor", "middle") 
        .style("font-weight", "bold") 
        .text(function(d) { return d; }); 

       svg.selectAll(".monthName") 
        .data(function(d) { return d3.time.months(new Date(d, 0, 1), new Date(d + 1, 0, 1)); }) 
        .enter().append("text") 
        .attr("x", function(d) {return (week(d) * cellSize + 50); }) 
        .attr("y", -5) 
        .style("text-anchor", "middle") 
        .text(function(d) { return monthName(d); }); 


       svg.selectAll(".dayName") 
        .data(function(d) { return ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"] }) 
        .enter().append("text") 
        .attr("x", -10) 
        .attr("y", function(d, i) {return (i * cellSize) + 12; }) 
        .style("text-anchor", "middle") 
        .text(function(d) { return d; }); 


       var svg1 = d3.select(element[0]).select("svg") 
       var legend = svg1.selectAll(".legend") 
        .data([0]) 
        .enter().append("g") 
        .attr("class", "legend") 
        .attr("transform", function(d, i) { 
        return "translate(130," + (i * (cellSize) + 30) + ")"; 
       }); 

       legend.append("svg:image") 
        .attr("xlink:href", "img/RA-scale-small.png") 
        .attr("x", width - 350) 
        .attr("y", 0) 
        .attr("width",200) 
        .attr("height", 47); 

       var rect = svg.selectAll(".day") 
        .data(function(d) { return d3.time.days(new Date(d, 0, 1), new Date(d + 1, 0, 1)); }) 
        .enter().append("rect") 
        .attr("class", "day") 
        .attr("width", cellSize) 
        .attr("height", cellSize) 
        .attr("x", function(d) { return week(d) * cellSize; }) 
        .attr("y", function(d) { return day(d) * cellSize; }) 
        .datum(format); 

       rect.append("title") 
        .text(function(d) { return d; }); 

       svg.selectAll(".month") 
        .data(function(d) { return d3.time.months(new Date(d, 0, 1), new Date(d + 1, 0, 1)); }) 
        .enter().append("path") 
        .attr("class", "month") 
        .attr("d", monthPath); 



       var data = d3.nest() 
        .key(function(d) { return d[scope.dateField]; }) 
        .rollup(function(d) {return {rank:d[0]["rank"],revenue:d[0]["abbrRevenue"],volume:d[0]["abbrVolume"]}}) 
        .map(newData); 

       rect.filter(function(d) { return d in data; }) 
        .attr("class", function(d) {return "day " + color(data[d].rank); }) 
        .select("title") 
        .text(function(d) { return d + "\nRevenue: " + data[d].revenue + "\nVolume: " + data[d].volume }); 
      } 
     }); 

     function monthPath(t0) { 
      var t1 = new Date(t0.getFullYear(), t0.getMonth() + 1, 0), 
       d0 = +day(t0), w0 = +week(t0), 
       d1 = +day(t1), w1 = +week(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"; 
     } 
    } 
} 

});

+0

歡迎來到StackOverflow。你有嘗試過什麼嗎?在這裏感謝努力! – Jensd

+0

我嘗試切換軸:'.attr(「x」,function(d){return day(d)* cellSize;}) .attr(「y」,function(d){return week(d)* cellSize ;})'然後使用月份路徑進行播放,但我努力獲取正確的月份路徑。 – user3356947

回答

1

經過大量的摸索和反覆試驗,我想出了一個解決方案。因此,我希望分享代碼,以防止其他人在那裏尋找類似的結果。

的代碼如下:

raApp.directive('heatMapYearWeekRows', function() { 
    var width = 1490, 
     height = 200, 
     cellSize = 17; // cell size 

    var day = d3.time.format("%w"), 
     week = d3.time.format("%U"), 
     month = d3.time.format("%m"), 
     monthName = d3.time.format("%b"), 
     format = d3.time.format("%Y-%m-%d"), 
     displayFormat = d3.time.format("%a, %d %b %Y"); 

    var color = d3.scale.quantize() 
     .domain([1, 5]) 
     .range(d3.range(5).map(function(d) { return "rank" + d; })); 

    return { 
     restrict: 'A' 
     , replace: false 
     , scope: { 
      chartData: '=' 
      , dateField: '=' 
     } 
     , link: function (scope, element, attrs) { 
      scope.$watch('chartData', function(newData, oldData) { 
       d3.select(element[0]).selectAll('*').remove(); 

       if (newData != undefined) { 
        var svg = d3.select(element[0]).selectAll("svg") 
         .data(function() { 
          var years = []; 

          for (var i = 0; i < newData.length; i++) { 
           var date = newData[i][scope.dateField]; 
           var year = parseInt(date.substring(0, 4)); 

           if (years.indexOf(year) == -1) { 
            years.push(year); 
           } 
          } 

          return years; 
         }) 
         .enter().append("svg") 
         .attr("width", width) 
         .attr("height", height) 
         .attr("class", "heatClass") 
         .append("g") 
         .attr("transform", "translate(" + 50 + "," + (height - cellSize * 7 - 1) + ")"); 

        svg.append("text") 
         .attr("transform", "translate(-30," + cellSize * 3.5 + ")rotate(-90)") 
         .style("text-anchor", "middle") 
         .style("font-weight", "bold") 
         .text(function(d) { return d; }); 

        svg.selectAll(".monthName") 
         .data(function(d) { return d3.time.months(new Date(d, 0, 1), new Date(d + 1, 0, 1)); }) 
         .enter().append("text") 
         .attr("x", function(d) { 
          return ((month(d) - 1) * (7 * cellSize) + 50); 
         }) 
         .attr("y", 115) 
         .style("text-anchor", "middle") 
         .style("font-weight", "bold") 
         .text(function(d) { return monthName(d); }); 

        var svg1 = d3.select(element[0]).select("svg") 
        var legend = svg1.selectAll(".legend") 
         .data([0]) 
         .enter().append("g") 
         .attr("class", "legend") 
         .attr("transform", function(d, i) { 
         return "translate(130," + (i * (cellSize) + 30) + ")"; 
        }); 

        legend.append("svg:image") 
         .attr("xlink:href", "img/RA-scale-small.png") 
         .attr("x", -80) 
         .attr("y", -30) 
         .attr("width",200) 
         .attr("height", 47); 

        var rect = svg.selectAll(".day") 
         .data(function(d) { return d3.time.days(new Date(d, 0, 1), new Date(d + 1, 0, 1)); }) 
         .enter().append("rect") 
         .attr("class", "day") 
         .attr("width", cellSize) 
         .attr("height", cellSize) 
         .attr("x", function(d) { 
          var prevDay = new Date(d -1); 
          var monthOffset = (month(d) - 1) * (7 * cellSize); 
          var result = (day(d) * cellSize) + +monthOffset; 
          return result; }) 
         .attr("y", function(d) { 
          var result = ((getMonthWeek(d) - 1) * cellSize); 
          return result; }) 
         .datum(format); 

        rect.append("title") 
         .text(function(d) { 
          return d; 
         }); 

        svg.selectAll(".month") 
         .data(function(d) { return d3.time.months(new Date(d, 0, 1), new Date(d + 1, 0, 1)); }) 
         .enter().append("path") 
         .attr("class", "month") 
         .attr("d", monthPath); 

        var data = d3.nest() 
         .key(function(d) { return d[scope.dateField]; }) 
         .rollup(function(d) {return {rank:d[0]["rank"],revenue:d[0]["abbrRevenue"],volume:d[0]["abbrVolume"]}}) 
         .map(newData); 

        rect.filter(function(d) { return d in data; }) 
         .attr("class", function(d) {return "day " + color(data[d].rank); }) 
         .select("title") 
         .text(function(d) { return displayFormat(new Date(d)) + "\nRevenue: " + data[d].revenue + "\nVolume: " + data[d].volume }); 
       } 
      }); 

      function getMonthWeek(date){ 
       var firstDay = new Date(date.getFullYear(), date.getMonth(), 1).getDay(); 
       return Math.ceil((date.getDate() + firstDay)/7); 
      } 

      function monthPath(t0) { 
       var t1 = new Date(t0.getFullYear(), t0.getMonth() + 1, 0), 
        d0 = +day(t0), w0 = +getMonthWeek(t0) -1, m0 = +month(t0), 
        d1 = +day(t1), w1 = +getMonthWeek(t1) -1; 
       var monthOffsetX = (+m0 - 1) * (7 * cellSize); 

       return "M" + ((d0 * cellSize) + +monthOffsetX) + "," + ((w0 + 1) * cellSize) 
        + "V" + w0 * cellSize + "H" + ((7 * cellSize) + +monthOffsetX) 
        + "V" + w1 * cellSize + "H" + (((d1 + 1) * cellSize) + +monthOffsetX) 
        + "V" + ((w1 + 1) * cellSize) + "H" + +monthOffsetX 
        + "V" + ((w0 + 1) * cellSize) + "Z"; 
      } 
     } 
    } 
}); 

希望有所幫助。