Published
Edited
Feb 10, 2019
Fork of Enneagram
Insert cell
Insert cell
quickRender(400, 400, context => {
const center = 200
const ringRadius = 140
const ringLineWidth = 4

// Ring
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])
}

// Lines
enneaConnections.forEach(([a, b], i ) => {
const [x1, y1] = enneaPoints[a]
const [x2, y2] = enneaPoints[b]
const lineAngle = Math.atan2(y2 - y1, x2 - x1)
// Draw just short of the label circumference
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();
})
// Arrow Heads
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();
})

// Labels
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)
})
})
Insert cell
enneaConnections = [
[0, 6],
[6, 3],
[3, 0],
[1, 4],
[4, 2],
[2, 8],
[8, 5],
[5, 7],
[7, 1]
]
Insert cell
enneaLabels = [
'C', 'D', 'A', 'E', 'B', 'C♯', 'G', 'E♭', 'F'
]
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more