JSFiddle - React, Tailwind, and code Playground
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800" width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
</svg>
</body>
</html>
CSS
body {
height: 100vh;
margin: 0;
}
svg {
pointer-events: none;
user-select: none;
vertical-align: bottom;
/* fjern inline-baseline */
font-family: serif;
font-size: 14pt;
}
svg .lines,
svg .notches {
fill: none;
stroke: #999;
}
svg .border {
fill: none;
stroke: #999;
stroke-width: 2;
}
svg .ring .highlight {
stroke: none;
fill: greenyellow;
fill-opacity: 0.25;
}
svg .now {
stroke: red;
stroke-opacity: 0.3;
stroke-width: 1;
fill: none;
}
JavaScript
const tick = false; // tick every second (true) or move smoothly (false)
const monthnames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
const daynames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
let numYears = 13;
// Segmented svg ring + static svg element creation helper function
class Ring {
static generateId() {
Ring.idCounter++;
return 'ring' + Ring.idCounter;
}
static mkSvgElem(name, attrs, cssClass = null) {
let elem = document.createElementNS('http://www.w3.org/2000/svg', name);
for (let attr of Object.keys(attrs)) {
elem.setAttribute(attr, attrs[attr]);
}
if (cssClass) {
elem.classList.add(cssClass);
}
return elem;
}
constructor(parent, outerRadius, innerRadius, labels, baseline = 0.5, vert = false) {
this.labels = labels;
this.slices = labels.length;
this.texts = [];
this.g = Ring.mkSvgElem('g', {}, 'ring');
const TWOPI = Math.PI + Math.PI;
const arc = TWOPI / this.slices;
const large = (arc > Math.PI ? '1' : '0');
const notches = [];
const radius = innerRadius + (outerRadius - innerRadius) * baseline; // middle
this.g.appendChild(Ring.mkSvgElem('circle', {
r: innerRadius
}, 'lines'));
this.g.appendChild(this.mkHighlight(innerRadius, outerRadius, arc, large));
let i = 0;
// generate arcs with text + notch lines
for (let label of labels) {
let angle = i / this.slices * TWOPI - Math.PI / 2;
notches.push(
'M', innerRadius * Math.cos(angle), innerRadius * Math.sin(angle),
'L', outerRadius * Math.cos(angle), outerRadius * Math.sin(angle)
);
let d;
if (vert) {
let a2 = angle + arc / 2;
d = [
'M', innerRadius * Math.cos(a2), innerRadius * Math.sin(a2),
'L', outerRadius * Math.cos(a2), outerRadius * Math.sin(a2)
]
} else {
...