d3.js日历视图行数周

时间:2014-02-27 08:34:11

标签: javascript d3.js calendar heatmap

任何人都可以帮我转换d3.js日历视图实现,它看起来像这里描述的那样(周作为列):D3 Calendar View using Associative Array

更像这样(周数为行):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";
        }
    }
}

});

1 个答案:

答案 0 :(得分: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";
            }
        }
    }
});

希望有所帮助。