【问题标题】:How to display just the weekdays on x-axis?如何在 x 轴上仅显示工作日?
【发布时间】:2020-12-16 13:51:59
【问题描述】:

我正在尝试使用 D3.js 绘制一个散点连接图。该图表使用 JSON 作为输入来显示 2020 年 1 月不同日期不同班次的人数。下面是我的代码。

<!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8">
  <title>Line Chart</title>
 <style>
   svg {
    font-family: Sans-Serif, Arial;
}
.line {
  stroke-width: 2;
  fill: none;
}

.axis path {
  stroke: black;
}

.text {
  font-size: 12px;
}

.title-text {
  font-size: 12px;
}
 </style>

</head>
<body>
<!-- partial:index.partial.html -->
<html>
  <head>
    <script src="https://d3js.org/d3.v4.min.js"></script>
  </head>
  <body>
    <div id="chart"></div>
  </body>
</html>
<!-- partial -->
  <script>

var data = [
  {
    name: "Regular",
    values: [
      {date: "2020-01-01", count: "2"},
      {date: "2020-01-02", count: "4"},
      {date: "2020-01-03", count: "8"},
      {date: "2020-01-04", count: "3"},
      {date: "2020-01-05", count: "5"}
    ]
  },
  {
    name: "Shift1",
    values: [
      {date: "2020-01-01", count: "2"},
      {date: "2020-01-02", count: "4"},
      {date: "2020-01-03", count: "8"},
      {date: "2020-01-04", count: "6"},
      {date: "2020-01-05", count: "1"}
    ]
  },
  {
    name: "Shift2",
    values: [
      {date: "2020-01-01", count: "3"},
      {date: "2020-01-02", count: "8"},
      {date: "2020-01-03", count: "4"},
      {date: "2020-01-04", count: "7"},
      {date: "2020-01-05", count: "6"}
    ]
  }
];

var width = 500;
var height = 300;
var margin = 50;
var duration = 250;

var lineOpacity = "0.25";
var lineOpacityHover = "0.85";
var otherLinesOpacityHover = "0.1";
var lineStroke = "1.5px";
var lineStrokeHover = "2.5px";

var circleOpacity = '0.85';
var circleOpacityOnLineHover = "0.25"
var circleRadius = 3;
var circleRadiusHover = 6;


/* Format Data */

var parseDate = d3.timeParse("%Y-%m-%d");
var formatTime = d3.timeFormat("%a");
data.forEach(function(d) { 
  d.values.forEach(function(d) {
    d.date = parseDate(d.date);
    d.count = +d.count;    
  });
});

/* Scale */
var xScale = d3.scaleTime()
  .domain(d3.extent(data[0].values, d => d.date))
  .range([0, width-margin]);

var yScale = d3.scaleLinear()
  .domain([0, d3.max(data[0].values, d => d.count)])
  .range([height-margin, 0]);

var color = d3.scaleOrdinal(d3.schemeCategory10);

/* Add SVG */
var svg = d3.select("#chart").append("svg")
  .attr("width", (width+margin)+"px")
  .attr("height", (height+margin)+"px")
  .append('g')
  .attr("transform", `translate(${margin}, ${margin})`);


/* Add line into SVG */
var line = d3.line()
  .x(d => xScale(d.date))
  .y(d => yScale(d.count));

let lines = svg.append('g')
  .attr('class', 'lines');

lines.selectAll('.line-group')
  .data(data).enter()
  .append('g')
  .attr('class', 'line-group')  
  .on("mouseover", function(d, i) {
      svg.append("text")
        .attr("class", "title-text")
        .style("fill", color(i))        
        .text(d.name)
        .attr("text-anchor", "middle")
        .attr("x", (width-margin)/2)
        .attr("y", 5);
    })
  .on("mouseout", function(d) {
      svg.select(".title-text").remove();
    })
  .append('path')
  .attr('class', 'line')  
  .attr('d', d => line(d.values))
  .style('stroke', (d, i) => color(i))
  .style('opacity', lineOpacity)
  .on("mouseover", function(d) {
      d3.selectAll('.line')
                    .style('opacity', otherLinesOpacityHover);
      d3.selectAll('.circle')
                    .style('opacity', circleOpacityOnLineHover);
      d3.select(this)
        .style('opacity', lineOpacityHover)
        .style("stroke-width", lineStrokeHover)
        .style("cursor", "pointer");
    })
  .on("mouseout", function(d) {
      d3.selectAll(".line")
                    .style('opacity', lineOpacity);
      d3.selectAll('.circle')
                    .style('opacity', circleOpacity);
      d3.select(this)
        .style("stroke-width", lineStroke)
        .style("cursor", "none");
    });


/* Add circles in the line */
lines.selectAll("circle-group")
  .data(data).enter()
  .append("g")
  .style("fill", (d, i) => color(i))
  .selectAll("circle")
  .data(d => d.values).enter()
  .append("g")
  .attr("class", "circle")  
  .on("mouseover", function(d) {
      d3.select(this)     
        .style("cursor", "pointer")
        .append("text")
        .attr("class", "text")
        .text(`${d.count}`)
        .attr("x", d => xScale(d.date) + 5)
        .attr("y", d => yScale(d.count) - 10);
    })
  .on("mouseout", function(d) {
      d3.select(this)
        .style("cursor", "none")  
        .transition()
        .duration(duration)
        .selectAll(".text").remove();
    })
  .append("circle")
  .attr("cx", d => xScale(d.date))
  .attr("cy", d => yScale(d.count))
  .attr("r", circleRadius)
  .style('opacity', circleOpacity)
  .on("mouseover", function(d) {
        d3.select(this)
          .transition()
          .duration(duration)
          .attr("r", circleRadiusHover);
      })
    .on("mouseout", function(d) {
        d3.select(this) 
          .transition()
          .duration(duration)
          .attr("r", circleRadius);  
      });


/* Add Axis into SVG */
var xAxis = d3.axisBottom(xScale).ticks(7);
var yAxis = d3.axisLeft(yScale).ticks(7);

svg.append("g")
  .attr("class", "x axis")
  .attr("transform", `translate(0, ${height-margin})`)
  .call(xAxis);

svg.append("g")
  .attr("class", "y axis")
  .call(yAxis)
  .append('text')
  .attr("y", 15)
  .attr("transform", "rotate(-90)")
  .attr("fill", "#000")
  .text("Total values");
  </script>

</body>
</html>

我不知道如何只在 x 轴上获取工作日,例如周一、周二等,而中间没有显示月份。

提前致谢

【问题讨论】:

    标签: javascript html css d3.js svg


    【解决方案1】:

    您需要调用tickFormat 函数传递所需的timeFormat 例如

    var xAxis = d3.axisBottom(xScale)
                .tickFormat(d3.timeFormat("%a"))
                .ticks(7);
    

    工作示例(可能不是您想要的,但应该向您展示如何控制轴标签。

    var data = [
      {
        name: "Regular",
        values: [
          {date: "2020-01-01", count: "2"},
          {date: "2020-01-02", count: "4"},
          {date: "2020-01-03", count: "8"},
          {date: "2020-01-04", count: "3"},
          {date: "2020-01-05", count: "5"}
        ]
      },
      {
        name: "Shift1",
        values: [
          {date: "2020-01-01", count: "2"},
          {date: "2020-01-02", count: "4"},
          {date: "2020-01-03", count: "8"},
          {date: "2020-01-04", count: "6"},
          {date: "2020-01-05", count: "1"}
        ]
      },
      {
        name: "Shift2",
        values: [
          {date: "2020-01-01", count: "3"},
          {date: "2020-01-02", count: "8"},
          {date: "2020-01-03", count: "4"},
          {date: "2020-01-04", count: "7"},
          {date: "2020-01-05", count: "6"}
        ]
      }
    ];
    
    var width = 500;
    var height = 300;
    var margin = 50;
    var duration = 250;
    
    var lineOpacity = "0.25";
    var lineOpacityHover = "0.85";
    var otherLinesOpacityHover = "0.1";
    var lineStroke = "1.5px";
    var lineStrokeHover = "2.5px";
    
    var circleOpacity = '0.85';
    var circleOpacityOnLineHover = "0.25"
    var circleRadius = 3;
    var circleRadiusHover = 6;
    
    
    /* Format Data */
    
    var parseDate = d3.timeParse("%Y-%m-%d");
    
    data.forEach(function(d) { 
      d.values.forEach(function(d) {
        d.date = parseDate(d.date);
        d.count = +d.count;    
      });
    });
    
    /* Scale */
    var xScale = d3.scaleTime()
      .domain(d3.extent(data[0].values, d => d.date))
      .range([0, width-margin]);
    
    var yScale = d3.scaleLinear()
      .domain([0, d3.max(data[0].values, d => d.count)])
      .range([height-margin, 0]);
    
    var color = d3.scaleOrdinal(d3.schemeCategory10);
    
    /* Add SVG */
    var svg = d3.select("#chart").append("svg")
      .attr("width", (width+margin)+"px")
      .attr("height", (height+margin)+"px")
      .append('g')
      .attr("transform", `translate(${margin}, ${margin})`);
    
    
    /* Add line into SVG */
    var line = d3.line()
      .x(d => xScale(d.date))
      .y(d => yScale(d.count));
    
    let lines = svg.append('g')
      .attr('class', 'lines');
    
    lines.selectAll('.line-group')
      .data(data).enter()
      .append('g')
      .attr('class', 'line-group')  
      .on("mouseover", function(d, i) {
          svg.append("text")
            .attr("class", "title-text")
            .style("fill", color(i))        
            .text(d.name)
            .attr("text-anchor", "middle")
            .attr("x", (width-margin)/2)
            .attr("y", 5);
        })
      .on("mouseout", function(d) {
          svg.select(".title-text").remove();
        })
      .append('path')
      .attr('class', 'line')  
      .attr('d', d => line(d.values))
      .style('stroke', (d, i) => color(i))
      .style('opacity', lineOpacity)
      .on("mouseover", function(d) {
          d3.selectAll('.line')
                        .style('opacity', otherLinesOpacityHover);
          d3.selectAll('.circle')
                        .style('opacity', circleOpacityOnLineHover);
          d3.select(this)
            .style('opacity', lineOpacityHover)
            .style("stroke-width", lineStrokeHover)
            .style("cursor", "pointer");
        })
      .on("mouseout", function(d) {
          d3.selectAll(".line")
                        .style('opacity', lineOpacity);
          d3.selectAll('.circle')
                        .style('opacity', circleOpacity);
          d3.select(this)
            .style("stroke-width", lineStroke)
            .style("cursor", "none");
        });
    
    
    /* Add circles in the line */
    lines.selectAll("circle-group")
      .data(data).enter()
      .append("g")
      .style("fill", (d, i) => color(i))
      .selectAll("circle")
      .data(d => d.values).enter()
      .append("g")
      .attr("class", "circle")  
      .on("mouseover", function(d) {
          d3.select(this)     
            .style("cursor", "pointer")
            .append("text")
            .attr("class", "text")
            .text(`${d.count}`)
            .attr("x", d => xScale(d.date) + 5)
            .attr("y", d => yScale(d.count) - 10);
        })
      .on("mouseout", function(d) {
          d3.select(this)
            .style("cursor", "none")  
            .transition()
            .duration(duration)
            .selectAll(".text").remove();
        })
      .append("circle")
      .attr("cx", d => xScale(d.date))
      .attr("cy", d => yScale(d.count))
      .attr("r", circleRadius)
      .style('opacity', circleOpacity)
      .on("mouseover", function(d) {
            d3.select(this)
              .transition()
              .duration(duration)
              .attr("r", circleRadiusHover);
          })
        .on("mouseout", function(d) {
            d3.select(this) 
              .transition()
              .duration(duration)
              .attr("r", circleRadius);  
          });
    
    
    /* Add Axis into SVG */
    var extent = d3.extent(data[0].values, d => d.date);
    var xAxis = d3.axisBottom(xScale)
                .tickFormat(d3.timeFormat("%a"))
                .ticks(Math.floor(( Date.parse(extent[1]) - Date.parse(extent[0]) ) / 86400000));
    
    var yAxis = d3.axisLeft(yScale).ticks(7);
    
    svg.append("g")
      .attr("class", "x axis")
      .attr("transform", `translate(0, ${height-margin})`)
      .call(xAxis);
    
    svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
      .append('text')
      .attr("y", 15)
      .attr("transform", "rotate(-90)")
      .attr("fill", "#000")
      .text("Total values");
    svg {
      font - family: Sans - Serif, Arial;
    }
    
    .line {
      stroke - width: 2;
      fill: none;
    }
    
    .axis path {
      stroke: black;
    }
    
    .text {
      font - size: 12 px;
    }
    
    .title - text {
      font - size: 12 px;
    }
    <html>
      <head>
        <script src="https://d3js.org/d3.v4.min.js"></script>
      </head>
      <body>
        <div id="chart"></div>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
      </body>
    </html>

    【讨论】:

    • @AmaarshallYaswankar - 太棒了!如果它对您有用并且您很高兴-那么通常您会接受答案。这不仅会帮助其他人解决同样的问题,而且还意味着人们将来更有可能帮助您解决您遇到的任何其他问题。您可以在此处阅读有关接受的信息:stackoverflow.com/help/accepted-answer
    【解决方案2】:

    也许在xAxis var 声明之后添加.tickFormat(d3.timeFormat("%a"))

    例如https://codepen.io/nufrankz/pen/VwabXzJ

    编辑: %a 用于短工作日,%A 用于完整工作日。完整列表here

    【讨论】:

      猜你喜欢
      • 2018-07-10
      • 2021-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-12
      • 2020-11-20
      • 2014-02-14
      • 2012-12-13
      相关资源
      最近更新 更多