欢迎光临
我们一直在努力

d3js绘制日历

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

<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. 交互功能:添加点击事件

    .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()实现动态数据绑定

参考文献

  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章时间数据处理
未经允许不得转载:九八云安全 » d3js绘制日历