JSFiddle - React, Tailwind, and code Playground

by Christian Sonne

HTML

<svg width="500" height="500" id="svg"></svg>

CSS

svg {
  outline: 1px red dotted;
}

JavaScript

let startDate = new Date();

function Calendar(container, startDate) {
  this.container = container;
  let [Y, M, D] = startDate.toISOString().split("T")[0].split("-").map(n => parseInt(n));
  this.startYear = Y;
  this.startMonth = M;
  this.startDate = new Date(`${Y}-${M}-01T00:00:00.000Z`);
  this.nMonths = 11;
  M += 12;
  if (M > 12) {
    M -= 12;
    Y++;
  }
  this.endDate = new Date(`${Y}-${M}-01T00:00:00.000Z`);
}

Calendar.prototype = {
  draw: function() {
    let radius = 200;
    let phase = Math.PI / 2;
    let nCategories = 5;
    let timerange = (this.endDate.getTime() - this.startDate.getTime());
    for (let c = 0; c < nCategories; c++) {
    	let Y = this.startYear;
    	let M = this.startMonth;
    	radius -= 20;
      let color = (nCategories - c - 1) * 255 / nCategories;
      for (let n = 0; n < this.nMonths; n++) {
        let path = document.createElementNS("http://www.w3.org/2000/svg", 'path');
        path.setAttribute("fill", `rgba(${color}, ${color}, ${color})`);
        let start = new Date(`${Y}-${M}-01T00:00:00.000Z`);
        let angle1 = phase + 2 * Math.PI - (start.getTime() - this.startDate.getTime()) * 2 * Math.PI / timerange;
        let x1 = 250 + Math.cos(angle1) * radius;
        let y1 = 250 + Math.sin(angle1) * radius;
        let x2 = 250 + Math.cos(angle1) * (radius + 20);
        let y2 = 250 + Math.sin(angle1) * (radius + 20);
        M++;
        if (M > 12) {
          M -= 12;
          Y++;
        }
        let end = new Date(`${Y}-${M}-01T00:00:00.000Z`);
        let angle2 = phase + 2 * Math.PI - (end.getTime() - this.startDate.getTime()) * 2 * Math.PI / timerange;
        let x3 = 250 + Math.cos(angle2) * (radius + 20);
        let y3 = 250 + Math.sin(angle2) * (radius + 20);
        let x4 = 250 + Math.cos(angle2) * radius;
        let y4 = 250 + Math.sin(angle2) * radius;
        
        let xo = Math.cos((angle1 + angle2)/2) * 5;
        let yo = Math.sin((angle1 + angle2)/2) * 5;
       ...