quickRender(400, 400, context => {
const center = 200
const ringRadius = 140
const ringLineWidth = 4
context.beginPath();
context.lineWidth = ringLineWidth
context.strokeStyle = "#dddddd"
context.arc(center, center, ringRadius, 0, 2 * Math.PI);
context.stroke();
context.font = "Bold 24px Arial"
context.textAlign = 'center'
let enneaPoints = []
for (let i = 0; i < 9; i++) {
const xPhase = Math.sin(i / 9 * 2 * Math.PI)
const yPhase = Math.cos(i / 9 * 2 * Math.PI)
const x = center + ringRadius * xPhase
const y = center - ringRadius * yPhase
enneaPoints.push([x, y])
}
enneaConnections.forEach(([a, b], i ) => {
const [x1, y1] = enneaPoints[a]
const [x2, y2] = enneaPoints[b]
const lineAngle = Math.atan2(y2 - y1, x2 - x1)
const x2a = x2 - 22 * Math.cos(lineAngle)
const y2a = y2 - 22 * Math.sin(lineAngle)
context.lineWidth = ringLineWidth
context.strokeStyle = `hsla(${enneaAngle(a)}, 40%, 70%, 50%)`
context.beginPath();
context.moveTo(x1, y1);
context.lineTo(x2a, y2a);
context.stroke();
})
enneaConnections.forEach(([a, b], i ) => {
const [x1, y1] = enneaPoints[a]
const [x2, y2] = enneaPoints[b]
const lineAngle = Math.atan2(y2 - y1, x2 - x1)
const xl = x2 - 37 * Math.cos(lineAngle - (15 / 360) * 2 * Math.PI)
const yl = y2 - 37 * Math.sin(lineAngle - (15 / 360) * 2 * Math.PI)
const xr = x2 - 37 * Math.cos(lineAngle + (15 / 360) * 2 * Math.PI)
const yr = y2 - 37 * Math.sin(lineAngle + (15 / 360) * 2 * Math.PI)
const x2a = x2 - 22 * Math.cos(lineAngle)
const y2a = y2 - 22 * Math.sin(lineAngle)
context.fillStyle = `hsl(${enneaAngle(a)}, 50%, 60%)`
context.beginPath();
context.moveTo(x2a, y2a);
context.lineTo(xl, yl);
context.lineTo(xr, yr);
context.lineTo(x2a, y2a);
context.fill();
})
enneaPoints.forEach(([x, y], i) => {
context.lineWidth = 4
context.fillStyle = `hsl(${enneaAngle(i)}, 50%, 60%)`
context.strokeStyle = `hsl(${enneaAngle(i)}, 30%, 50%)`
context.beginPath();
context.arc(x, y, 22, 0, 2 * Math.PI);
context.fill();
context.stroke();
context.fillStyle = '#ffffff'
context.fillText(enneaLabels[i], x, y + 8)
})
})