首页 > 解决方案 > 删除 d3js 日历中的周末

问题描述

在下面的片段中,我有一个常规的年历,我现在尝试做的是使用以下代码排除周末。

var day = function(d) { 
        if (d.getDay() == 0 || d.getDay() == 6) return null;
        return d.getDay(); 
    }

但它并没有像我希望的那样工作。

如果这需要对函数进行太大的重构,monthPath那么我将研究另一种类型的日历。

这是代码:

var width = 960,
    height = 136,
    cellSize = 17,
    trans_1 = ((width - cellSize * 53) / 2),
    trans_2 = (height - cellSize * 7 - 1);

var day = function(d) { 
        // filter out weekends 
        if (d.getDay() == 0 || d.getDay() == 6) return null;
        return d.getDay(); 
    },
    week = d3.timeFormat("%U"),
    date = d3.timeFormat("%Y-%m-%d");

var svg = d3.select("body").selectAll("svg")
    .data([2018])
  .enter().append("svg")
    .attr("width", width)
    .attr("height", height)
  .append("g")
    .attr("transform", 
        "translate(" + trans_1 + "," + trans_2 + ")");

var rect = svg.selectAll(".day")
    .data(function(d) { 
        return d3.timeDays(
            new Date(d, 0, 1), new Date(d + 1, 0, 1));
    })
  .enter().append("rect")
    .attr("class", "day")
    .attr("width", cellSize)
    .attr("height", cellSize)
    .attr("x", d => week(d) * cellSize)
    .attr("y", d => day(d) * cellSize)
    .datum(date);

svg.selectAll(".month")
    .data(function(d) { 
        return d3.timeMonths(
            new Date(d, 0, 1), new Date(d + 1, 0, 1));
    })
  .enter().append("path")
    .attr("class", "month")
    .attr("d", monthPath);

function monthPath(t0) {
    var t1 = new Date(t0.getFullYear(), t0.getMonth() + 1, 0),
        d0 = +day(t0), w0 = +week(t0),
        d1 = +day(t1), w1 = +week(t1);
    return "M" + (w0 + 1) * cellSize + "," + d0 * cellSize
         + "H" + w0 * cellSize + "V" + 7 * cellSize
         + "H" + w1 * cellSize + "V" + (d1 + 1) * cellSize
         + "H" + (w1 + 1) * cellSize + "V" + 0
         + "H" + (w0 + 1) * cellSize + "Z";
}
body {
    padding-top: 25px;
    width: 1000px;
    margin: auto;
}
.day {
    fill: #fff;
    stroke: #ccc;
}
.month {
    fill: none;
    stroke: #000;
    stroke-width: 2px;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<meta charset="utf-8">

标签: javascriptd3.js

解决方案


要从您的月份路径中删除周末,首先更改顶部和底部垂直点。之前的最小值是0(对于第 0 天的顶部边缘,星期日),但由于我们正在消除它,它现在将是1(对于第 1 天,星期一)* cellSize。最大值是周六的底边,所以 day 6 + 1(for the bottom edge) * cellSize,但由于周六被淘汰,新的底边是周五(第 5 天),即5+1 * cellSize。这给出了:

    return "M" + (w0 + 1) * cellSize + "," + d0 * cellSize
         + "H" + w0 * cellSize + "V" + 6 * cellSize // note change
         + "H" + w1 * cellSize + "V" + (d1 + 1) * cellSize
         + "H" + (w1 + 1) * cellSize + "V" + cellSize     // note change
         + "H" + (w0 + 1) * cellSize + "Z";

我们还需要更改该月的第一天和最后一天。如果第一天是星期日,则“向上取整”到星期一:

    d0 = +day(t0) === 0 ? 1 : +day(t0)

同样,如果最后一天是星期六,则将其“四舍五入”为星期五:

    d1 = +day(t1) === 6 ? 5 : +day(t1)

把所有这些放在一起,我们得到:

    var t1 = new Date(t0.getFullYear(), t0.getMonth() + 1, 0),
        d0 = +day(t0) === 0 ? 1 : +day(t0),
        w0 = +week(t0),
        d1 = +day(t1) === 6 ? 5 : +day(t1),
        w1 = +week(t1);
    return "M" + (w0 + 1) * cellSize + "," + d0 * cellSize
         + "H" + w0 * cellSize + "V" + 6 * cellSize // note change
         + "H" + w1 * cellSize + "V" + (d1 + 1) * cellSize
         + "H" + (w1 + 1) * cellSize + "V" + cellSize     // note change
         + "H" + (w0 + 1) * cellSize + "Z";

var width = 960,
  height = 150,
  cellSize = 17,
  trans_1 = ((width - cellSize * 53) / 2),
  trans_2 = (height - cellSize * 7 - 1);

var day = function(d) {
    // filter out weekends 
    //            if (d.getDay() == 0 || d.getDay() == 6) return null;
    return d.getDay();
  },
  week = d3.timeFormat("%U"),
  date = d3.timeFormat("%Y-%m-%d");

var svg = d3.select("body").selectAll("svg")
  .data([2018])
  .enter().append("svg")
  .attr("width", width)
  .attr("height", height)
  .append("g")
  .attr("transform",
    "translate(" + trans_1 + "," + trans_2 + ")");

var rect = svg.selectAll(".day")
  .data(function(d) {
    return d3.timeDays(new Date(d, 0, 1), new Date(d + 1, 0, 1))
  })
  .enter().append("rect")
  .attr("class", function(d) {
    return "day _" + d.getDay()
  })
  .attr("width", cellSize)
  .attr("height", cellSize)
  .attr("x", d => week(d) * cellSize)
  .attr("y", d => day(d) * cellSize)
  .datum(date);

svg.selectAll(".month")
  .data(function(d) {
    return d3.timeMonths(
      new Date(d, 0, 1), new Date(d + 1, 0, 1));
  })
  .enter().append("path")
  .attr("class", "month")
  .attr("d", monthPath);

function monthPath(t0) {
  var t1 = new Date(t0.getFullYear(), t0.getMonth() + 1, 0),
    d0 = +day(t0) === 0 ? 1 : +day(t0),
    w0 = +week(t0),
    d1 = +day(t1) === 6 ? 5 : +day(t1),
    w1 = +week(t1);
  return "M" + (w0 + 1) * cellSize + "," + d0 * cellSize +
    "H" + w0 * cellSize + "V" + 6 * cellSize // note change
    +
    "H" + w1 * cellSize + "V" + (d1 + 1) * cellSize +
    "H" + (w1 + 1) * cellSize + "V" + cellSize // note change
    +
    "H" + (w0 + 1) * cellSize + "Z";
}
body {
  padding-top: 25px;
  width: 1000px;
  margin: auto;
}

.day {
  fill: #fff;
  stroke: #ccc;
}

.month {
  fill: none;
  stroke: #000;
  stroke-width: 2px;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<meta charset="utf-8">

顺便说一句,您过滤掉周末的策略会(有点)删除代表一周中的几天的网格单元:

var rect = svg.selectAll(".day")
  .data(function(d) {
    return d3.timeDays(new Date(d, 0, 1), new Date(d + 1, 0, 1))
    .filter( function(x){
      return (x.getDay() !== 6 && x.getDay() !== 0) // filter out day 0 and 6
    })
  })
  .enter().append("rect")
  // etc.

推荐阅读