What is the best way to show only the weekdays on the x-axis?

My goal is to create a scatter-linked graph using D3.js, showcasing the people count for various shifts on different dates in January 2020. Here is the code snippet I am working with:

<!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>
  ...

I am seeking assistance in displaying only weekdays (Mon, Tue, etc.) on the x-axis without showing the month in between. Any help would be greatly appreciated!

Thank you.

Answer №1

To enhance your code, consider adding

.tickFormat(d3.timeFormat("%a"))
right after declaring the xAxis variable.

For an example, check out this link: https://codepen.io/nufrankz/pen/VwabXzJ

UPDATE: Use %a for abbreviated weekdays and %A for full weekday names. You can find a complete list of formatting options here

Answer №2

Make sure to utilize the tickFormat function with your desired timeFormat, for example:

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

Here is a practical demonstration that may not be precisely what you need, but it demonstrates how to manage axis labels.

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;


/* Data Formatting */

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;    
  });
});

/* Scaling */
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);

/* Append 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 to 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 on 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 to 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: 12px;
}

.title-text {
  font-size: 12px;
}
<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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

No entries found in the Nuxt/content module's array

<template> <div> <input v-model="searchQuery" type="search" autocomplete="off" placeholder="Search Articles" /> <ul v-if="articles.length"> ...

Chat application using Node.js without the need for Socket.IO

Recently delving into the world of Node.js, I stumbled upon the fs.watchFile() method. It got me thinking - could a chat website be effectively constructed using this method (along with fs.writeFile()) in comparison to Socket.IO? While Socket.IO is reliabl ...

Exploring the ins and outs of flexbox and utilizing overflow:auto

In my current situation, I have successfully resolved all cases but am now seeking assistance in debugging my mental model. Specifically, I am focusing solely on Chrome for the sake of simplicity. Within my nested "holy grail-ish" flexbox layouts, I have ...

Incorporate a distinct identifier for every menu item within the Material UI TablePagination

Can a unique identifier be assigned to each menu item generated using the <TablePagination> component? I would like to add a specific ID (e.g., id="menu_item_0", id="menu_item_1" & id="menu_item_2") to the menu item ...

generate a collection using a string of variables

I'm looking for a way to pass a string as the name of an array to a function, and have that function create the array. For example: createArray('array_name', data); function createArray(array_name, data){ var new_array = []; // pe ...

Creating a CSS Grid with Full-Width Columns and Consistent Margins

Currently, I am attempting to create a responsive grid with 4 columns that expands to the entire width of the screen on desktop displays. However, when I introduce margins to space them out evenly, I encounter an issue where the last column either doesn&ap ...

JavaScript: Efficiently Sorting a Multidimensional Array

Here is the array that needs to be sorted based on the third item: const array = [ [1, "Convention Hall", "Mumbai", 10, "XYZ Company"], [2, "Auditorium", "Delhi", 10, "ABC Company"], [3, "CenterHall", "Bangalore", 10, "ZZZ Company"], ... ...

Understanding the mechanics of utilizing node modules and requiring them within an Express 4 router

After initiating a node project using an express 4 generator, I have set up the following routing code in the /routes/index.js file: // ./routes/index.js var express = require('express'); var router = express.Router(); router.get('/' ...

Executing multiple nested `getJSON` requests in a synchronous manner using jQuery

I am facing an issue with my code that connects to an API using $.getJSON. It retrieves JSON data and then iterates three times through a for loop because the data has 3 objects. During each of these iterations, it makes another $.getJSON call to fetch spe ...

Unveiling the enigma of unresponsive Bootstrap dropdowns

I'm working on creating a custom navigation bar using Bootstrap v5. I found the code on the Bootstrap website and copied it into my project. However, I also added some JavaScript code to enhance its functionality, but unfortunately, it's not work ...

Transmitting Data to PHP Using JQuery/AJAX

I'm struggling with this issue. Here is the HTML code that I have: <input type="text" class="studno"><input type="button" value="Check" class="chstudno"> How can I send this data to PHP using JQuery/AJAX? Below is the code that I current ...

send document through ajax

Having some trouble with this task. Here is what I've managed to put together so far: <input id="newFile" type="file"/> <span style="background-color:orange;" onClick="newImage()">HEYTRY</span> I know it's not much progress. ...

Acquiring XML data directly in jQuery without any preprocessing

Hey there, I'm dealing with an unusual situation. I need to extract data from an API that returns malformed XML. Each <episode> in the response has its own <title> tag. However, when using $.get or $.ajax, all these titles end up in the &l ...

Creating a smooth entrance effect in VueJS using CSS transitions is a breeze

Even though it seems simple, I am struggling to get it to work properly. My goal is to have the existing elements in my list shift to make room for a new element added, and then have the new element appear with a smooth fade transition. I have tried to im ...

Strategies for preventing multi-level inheritance of TypeScript class properties and methods

In my current JavaScript class structure, the DataService is defined as follows: // data.service.ts export class DataService { public url = environment.url; constructor( private uri: string, private httpClient: HttpClient, ) { } ...

There is an error in ReactJS: TypeError - _this.props.match is not defined

I am experiencing a TypeError in my console tab and I can't seem to figure out where the error is occurring in my source code. I am relatively new to ReactJS so any help in identifying what I'm doing wrong would be greatly appreciated. Thank you ...

Creating a Slider with a Multitude of Images

I am working on a project to develop a gallery that pulls images from a JSON source. I have successfully implemented infinite scrolling to display the images on the first page. However, I am now facing a challenge when it comes to showing the selected imag ...

Navigating JSON data with unexpected fields in Typescript and React.js

Looking to parse a JSON string with random fields in Typescript, without prior knowledge of the field types. I want to convert the JSON string into an object with default field types, such as strings. The current parsing method is: let values = JSON.parse ...

The addition and deletion of classes can sometimes lead to disruptions in the DOM

I've been struggling to phrase this question for a while now. I'm working on a single-page e-commerce site that operates by modifying the HTML in divs and using CSS along with JQuery to show and hide those divs. My problem arises when, occasional ...

Several features - Second function malfunctioning

The initial inquiry is effective. However, the subsequent one is encountering issues as it is failing to confirm if an email contains the "@" symbol. My attempted solution involved reordering the functions related to email validation. <body onload="ch ...