当前位置:首页 > 行业动态 > 正文

d3js绘制日历

D3.js可通过数据绑定动态生成日历视图,利用SVG绘制日期格子,结合时间尺度布局月份,支持交互高亮与数据展示,适用于可视化日程、习惯追踪等场景,灵活自定义样式与事件响应。

要在网页上使用D3.js创建日历可视化,可以通过以下步骤实现一个交互式日历,本教程以2024年9月为例,完整代码可直接嵌入网页使用。

实现原理

日历本质上是二维日期矩阵的可视化映射,通过D3的布局算法,我们将日期数据转换为:

d3js绘制日历

  1. 按周分组的日期矩阵
  2. 日期与坐标的对应关系
  3. 可视化元素的样式绑定

核心代码实现

<div id="calendar"></div>
<script src="https://d3js.org/d3.v7.min.js"></script>
<script>
// 基础配置
const width = 800;
const cellSize = 80;
const weekDays = ["日", "一", "二", "三", "四", "五", "六"];
// 创建SVG画布
const svg = d3.select("#calendar")
  .append("svg")
  .attr("width", width)
  .attr("height", cellSize * 7);
// 生成日期数据集
const startDate = new Date(2024, 8, 1); // 2024年9月1日
const endDate = new Date(2024, 9, 0); // 获取9月最后一天
const dates = d3.timeDays(startDate, endDate);
// 创建日历布局
const calendarLayout = d3.timeWeek
  .range(startDate, endDate)
  .map(week => d3.timeDay.range(week, d3.timeDay.offset(week, 7)));
// 绘制日历格子
svg.selectAll(".week")
  .data(calendarLayout)
  .enter().append("g")
  .attr("transform", (d,i) => `translate(0,${i * cellSize})`)
  .selectAll(".day")
  .data(d => d)
  .enter().append("rect")
  .attr("class", "day-cell")
  .attr("x", (d,i) => i * cellSize)
  .attr("width", cellSize - 2)
  .attr("height", cellSize - 2)
  .style("fill", d => d.getMonth() === 8 ? "#fff" : "#f5f5f5") // 非本月日期
  .style("stroke", "#eee");
// 添加日期文字
svg.selectAll(".day-text")
  .data(dates)
  .enter().append("text")
  .attr("x", (d,i) => {
    const week = Math.floor(i / 7);
    return (i % 7) * cellSize + 10;
  })
  .attr("y", (d,i) => Math.floor(i / 7) * cellSize + 30)
  .text(d => d.getDate())
  .style("font-size", "24px")
  .style("fill", d => d.getDay() === 0 ? "red" : "#333");
// 添加周次标识
svg.append("g")
  .selectAll("text")
  .data(weekDays)
  .enter().append("text")
  .attr("x", (d,i) => i * cellSize + 30)
  .attr("y", 20)
  .text(d => d)
  .style("font-weight", "bold");
</script>
<style>
.day-cell:hover {
  fill: #e3f2fd !important;
  cursor: pointer;
}
text {
  font-family: 'Arial', sans-serif;
  user-select: none;
}
</style>

扩展功能建议

  1. 数据绑定:通过.datum()方法关联每日数据

    .day-cell.datum(function(d) {
    return {
     date: d,
     value: Math.random() * 100 // 示例数据
    };
    })
  2. 交互功能:添加点击事件

    d3js绘制日历

    .on("click", function(event, d) {
    d3.select(this).style("fill", "#b3e5fc");
    console.log("选中日期:", d.toLocaleDateString());
    })
  3. 热力效果:根据数据值染色

    .style("fill", d => {
    const value = d.value || 0;
    return d3.interpolateBlues(value/100);
    })

技术要点

  1. 时间计算:使用d3.timeDays生成完整日期序列
  2. 矩阵布局:通过d3.timeWeek创建周次分组
  3. 坐标映射:通过(i % 7)计算横向坐标,Math.floor(i/7)计算纵向坐标
  4. 性能优化:使用虚拟DOM进行批量元素操作

适配调整建议

  • 响应式布局:添加viewBox属性实现自适应
    .attr("viewBox", `0 0 ${width} ${cellSize*6}`)
  • 国际化:使用d3.timeFormat适配不同日期格式
  • 数据加载:结合d3.json()实现动态数据绑定

参考文献

d3js绘制日历

  1. D3官方日历示例 (https://observablehq.com/@d3/calendar)
  2. MDN Date对象文档 (https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date)
  3. 《Interactive Data Visualization for the Web》第二版,第7章时间数据处理