d3:custom-time-axis

by Richard Hunter

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script>

CSS

svg {
  background: #fff1e5;
}

JavaScript

const margins = {
  top: 2,
  bottom: 50,
  left: 20,
  right: 20,
};

const formatDate = d3.timeFormat('%m-%y');

const width = 700;
const height = 400;

const min = new Date(2022, 0, 1);
const max = new Date(2023, 6, 1);

const xScale = d3.scaleTime()
  .domain([min, max])
  .range([margins.left, width - margins.right]);

const svg = renderSVG(width, height);

function renderSVG(width, height) {
  return d3.select('body')
    .append('svg')
    .attr('width', width)
    .attr('height', height);
}

renderLine(svg, margins.left, height - margins.bottom, width - margins.right, height - margins.bottom);

renderTick(svg, new Date(2022, 3, 1));
renderTick(svg, new Date(2022, 6, 1));
renderTick(svg, new Date(2022, 9, 1));
renderTick(svg, new Date(2023, 0, 1));
renderTick(svg, new Date(2023, 3, 1));

renderGraphLine();

function renderTick(svg, date) {
  const x = xScale(date);
  renderLine(svg, x, height - margins.bottom, x, height - margins.bottom + 10);

  svg.append('text')
    .attr('x', x)
    .attr('y', height - margins.bottom + 20)
    .text(formatDate(date))
    .attr('text-anchor', 'middle')
    .attr('font-family', 'arial')
    .attr('font-size', 12)
}

function renderLine(svg, x1, y1, x2, y2) {
  svg.append('line')
    .attr('x1', x1)
    .attr('y1', y1)
    .attr('x2', x2)
    .attr('y2', y2)
    .attr('stroke', 'blue')
    .attr('shape-rendering', 'crispEdges')
}