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;
})
绘制
具体绘制方法与之前博文相似,只需要分别绘制各个矩形即可,不再列出代码。