JSFiddle - React, Tailwind, and code Playground

by m1erickson

HTML

<canvas id="canvas" width=775 height=650></canvas>

CSS

body{ background-color: ivory; }
canvas{border:1px solid red;}

JavaScript

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var year = 2014;
var PI2 = Math.PI * 2;
var cx = 375;
var cy = 375;
var radialIncrement = 15;
var rotationIncrement = -Math.PI / 31;

var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
var days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
var dayNames = ['Su', 'M', 'Tu', 'W', 'Th', 'F', 'Sa', 'Su', 'M', 'Tu', 'W', 'Th', 'F', 'Sa', 'Su', 'M', 'Tu', 'W', 'Th', 'F', 'Sa', 'Su', 'M', 'Tu', 'W', 'Th', 'F', 'Sa', 'Su', 'M', 'Tu', 'W', 'Th', 'F', 'Sa', 'Su', 'M', 'Tu', 'W', 'Th', 'F', 'Sa'];

var monthsFirstWeekday = []
for (var m = 1; m <= 12; m++) {
    monthsFirstWeekday.push(new Date(m + "/01/" + year).getDay());
}


for (var d = 0; d <= 38; d++) {
    ctx.save();
    ctx.translate(cx, cy);
    ctx.rotate(rotationIncrement * (31 - d) + Math.PI / 2);
    var x = -3;
    var y = -13 * radialIncrement - 150;
    ctx.font = "12px verdana";
    ctx.fillStyle = "blue";
    ctx.fillText(dayNames[d], x, y);
    ctx.restore();
}

for (var m = 0; m < months.length; m++) {
    ctx.save();
    ctx.translate(cx, cy + 25);
    ctx.rotate(Math.PI * 3 / 2);
    ctx.fillStyle = "blue";
    ctx.fillText(months[m], 0, -(months.length - m) * radialIncrement - 150);
    ctx.restore();
}

for (var d = 0; d <= 38; d++) {

    ctx.save();
    ctx.translate(cx, cy);
    ctx.rotate(rotationIncrement * (31 - d) + Math.PI / 2);

    for (var m = 0; m < months.length; m++) {

        var x = 0;
        var y = -(months.length - m) * radialIncrement - 150;

        var dd = d - monthsFirstWeekday[m] + 1;

        if (dd > 0 && dd <= days[m]) {
            ctx.fillStyle = "black";
            ctx.fillText(dd, x, y);
        } else {
            ctx.beginPath();
            ctx.arc(x + 3, y, 1, 0, Math.PI * 2);
            ctx.closePath();
            ctx.fillStyle = "red";
            ctx.fill();
        }

    }
    ctx.restore();
}