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