You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于D3.js的单月热力图日历开发:月份切换与日期点击

基于D3.js的单月热力图日历开发需求与实现

输入图片描述

我正在开发基于D3.js的单月热力图日历,仅展示单个月份,通过左右箭头切换月份。当医护人员有预约时,需增强对应日期的热力效果。

用于展示该人员日程的叠加数据示例如下,我需要添加切换箭头、实现月份切换功能,同时返回当前点击的日期。

2023年7月27日 最新代码实现如下:

<html>

  <head>
    <title>Heatmap d3</title>
    <script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
    <style>

    </style>
  </head>

  <body>



    <script>
      var data = [{
          "date": "2023-07-10",
          "value": "211"
        },{
          "date": "2023-07-20",
          "value": "2"
        },
        {
          "date": "2023-07-21",
          "value": "5"
        },
        {
          "date": "2023-07-22",
          "value": "5"
        },
        {
          "date": "2023-07-23",
          "value": "0"
        },
        {
          "date": "2023-07-24",
          "value": "8"
        },
        {
          "date": "2023-07-25",
          "value": "3"
        },
        {
          "date": "2023-07-26",
          "value": "1"
        }
      ]


      var width = 300,
        height = 450,
        cellSize = 35; // cell size
      week_days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
      month = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

      var day = d3.timeFormat("%w"),
        week = d3.timeFormat("%U"),
        format = d3.timeFormat("%Y%m%d");
      parseDate = d3.timeFormat("%Y%m%d").parse;

      var color = d3.scaleLinear().range(["white", '#002b53'])
        .domain([0, 1])

      var svg = d3.select("body").append("svg")
        .attr("height", height)
        .attr("width", width)
        .attr("class", "calendar")
        .append("g")
        .attr("transform", "translate(10, 10)");

      var leg = svg.append("g")
        .attr("class", "leg")
        .attr("transform", "translate(10, 10)");

      var chart = svg.append("g")
        .attr("class", "chart")
        .attr("transform", "translate(25, -850)");
      //
      const d = new Date();
      let name = month[d.getMonth()];
      //console.log("name", name);


      let pickedYear = 2023;
      let pickedMonth = 7; //July

      const daysInMonth = (year, month) => new Date(year, month, 0).getDate();

      //console.log("daysInMonth", daysInMonth(pickedYear, pickedMonth));

      let dz = 1;
      //console.log("xx", d3.timeDays(new Date(pickedYear+"-"+pickedMonth+"-1"), new Date(pickedYear+"-"+pickedMonth+"-31")) )

      //console.log("ccccc",  new Date(pickedYear+"-"+pickedMonth+"-"+daysInMonth)  )

      function formatDate(date) {
        var d = new Date(date),
          month = '' + (d.getMonth() + 1),
          day = '' + d.getDate(),
          year = d.getFullYear();

        if (month.length < 2)
          month = '0' + month;
        if (day.length < 2)
          day = '0' + day;

        return [year, month, day].join('-');
      }

      function opacityCal(val) {
        var opacity = 0.1;

        opacity = opacity * val;

        //if val is 0 - consider it a spare day no change in opacity
        if (val === 0 || val >= 10) {
          opacity = 1;
        }

        return opacity;
      }

      //
      var padding = 5;

      var rect = chart.selectAll(".day")
        .data(function(d) {
          return d3.timeDays(new Date("2023-07-1"), new Date("2023-07-31"));
        })
        .enter()
        .append("rect")
        .attr("class", function(d) {
          return "day " + "date" + formatDate(d);
        })
        .attr("data-date", function(d) {
          return formatDate(d);
        })
        .attr("width", cellSize)
        .attr("height", cellSize)
        .attr("x", function(d) {
            //console.log("d", d)
          return day(d) * cellSize;
        })
        .attr("y", function(d) {
          return week(d) * cellSize;
        })
        .attr("fill", '#f2f2f2')
        .attr("stroke", 'white')
        .attr("stroke-width", '7')
        .on("mouseover", function(d) {
          d3.select(event.currentTarget)
            .style("fill", "#d9e3a6");
        })
        .on("mouseout", function(d) {
          d3.select(event.currentTarget)
            .style("fill", "#f2f2f2");
        })
        .on("click", function(d,i){
            let date = d3.select(event.currentTarget).attr("data-date");
            console.log("date", date)
            return date;
        })
        .datum(format);

      var legend = leg.selectAll(".legend")
        .data(week_days)
        .enter().append("g")
        .attr("class", "legend")
        .attr("transform", function(d, i) {
          return "translate(" + (((i + 1) * 35) + 5) + ",0)";
        });

      legend.append("text")
        .attr("class", function(d, i) {
          return week_days[i]
        })
        .style("text-anchor", "end")
        .attr("dy", "-.25em")
        .text(function(d, i) {
          return week_days[i]
        });


      for (let i = 0; i < data.length; i++) {


        d3.selectAll('.' + "date" + formatDate(data[i].date))
          .attr("fill", "#f8600d")
          .attr("opacity", opacityCal(parseInt(data[i].value)))
          .on("mouseover", function(d) {
            d3.select(event.currentTarget)
              .style("fill", "#d9e3a6")
              .attr("opacity", 1)
          })
          .on("mouseout", function(d) {
            d3.select(event.currentTarget)
              .style("fill", "#f8600d")
              .attr("opacity", opacityCal(parseInt(data[i].value)))
          })

      }

    </script>



  </body>

</html>

内容的提问来源于stack exchange,提问作者The Old County

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 07:05:16