D3.js学习笔记:绘制日历(2)

目录

之前一篇博文《[D3.js学习笔记:绘制日历](https://blog.perillaroc.wang/post/2015/2015-01-05-d3-notebook-draw-calendar/》介绍我如何仿制github全年日历,本文介绍我仿制月份日历。示例截图:

我用一个中午的时间仿制上面的网页,截图如下:

大致模拟出样例的表现形式,细节有待进一步处理。

分析

时间范围从某月1号所在星期的星期一开始,连续六周,共42天。

数据分两种,上面的矩形框每个过去的日期都有,下面的矩形框只有特定的日期才有。其实这两种数据可以看做是同一个形式,只不过一种是连续时间序列,另一种只有离散数据点,采用相同的方式处理。

我选择使用rect矩形来绘出各个元素:日期网格、日期标签、两个数据标签。

实现

数据准备

使用D3提供的函数来生成日期序列。

假定提供某个月份的任意一个日期

var query_day=new Date()

当前月份的1号所在星期的星期一

var start_day = d3.time.monday(d3.time.month(query_day));

6周后的周日

var end_day = d3.time.day.offset(start_day, 42);

生成日期序列

var end_day = d3.time.day.offset(start_day, 42);

坐标

javascript中默认一周的第一天是周日,而我们平时以周一为第一天,所以在计算纵坐标时要计算当前日期前一天所在的周数。
六周的序列

var week_range = d3.time.weeks(d3.time.day.offset(start_day, -1), d3.time.day.offset(end_day, -1));

纵坐标

var y_week_scale = d3.scale.ordinal().domain(week_range).rangeBands([0,6]);
// ...
day_grid_groups.append('rect')
    // ...
    .attr('y', function(d){
        var day = d3.time.day.offset(d, -1);
        return y_week_scale(d3.time.week(day)) * cell_height;
    })

横坐标也需要计算当前日期的前一天。

var x_format = d3.time.format("%w");
// ...
day_grid_groups.append('rect')
    // ...
    .attr('x', function(d){
        var day = d3.time.day.offset(d, -1);
        return x_format(day) * cell_width;
    })

绘制

具体绘制方法与之前博文相似,只需要分别绘制各个矩形即可,不再列出代码。