Published
Edited
Aug 19, 2022
Fork of Compass Rose
1 star
Insert cell
Insert cell
Insert cell
svg`<svg width="${size}" height="${size}" viewBox="${-size/2} ${-size/2} ${size} ${size}">
${repeat(tick(radius, 5, '#434343'), numMinorTicks * 4 * numMajorTicks)}
${repeat(tick(radius, 8), numMajorTicks * 4)}
${repeat(`<path d="M 0,-${radius+14} l 3,10 l -6,0 z" fill="black" stroke="black" stroke-width="1"/>`, 4, 0)}
${repeat(`<path d="M 0,-${radius+14} l 3,10 l -6,0 z" fill="white" stroke="black" stroke-width="1"/>`, 4, 45)}
<circle r="${radius}" fill="#d3d3d3" stroke="#434343" stroke-width="3" />
${repeat(directionMarker(radius+14, 17), 4, 0)}
${repeat(directionMarker(radius+12, 12), 4, 45)}
${repeat(angleMarker(84, 7), 24)}
${repeat(pie(radius-margin/2, 2 * Math.PI * (radius-margin/2) / colors.length / 2, 1, colors), colors.length, 360/colors.length/2)}
</svg>
`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function pie(radius, width, narrowness=1.0, colors) {
return (_, i) => `<path d="M 0,0 L ${-width},${-radius} A ${width} ${width/2} 0 1 1 ${width} ${-radius} z" fill="${colors[i]}" stroke="black" stroke-width="0.5"/>`;
}
Insert cell
function tick(radius, length, color='black') {
return `<path d="M 0,${-radius} l 0,${-length}" fill="none" stroke="${color}" stroke-width="1" />`;
}
Insert cell
function directionMarker(radius, fontSize) { return (angle, _) => {
let label = {0: 'N', 45: 'NE', 90: 'E', 135: 'SE', 180: 'S', 225: 'SW', 270: 'W', 315: 'NW'}[angle] ?? '??';
return `<text y="${-radius-(margin/2)}" font-size="${fontSize}" text-anchor="middle" dy="0.4em">${label}</text>`;
};
}
Insert cell
angleMarker = function(radius, fontSize) { return (angle, _) => {
if ([0, 45, 90, 135, 180, 225, 270, 315].includes(angle)) return ``;
return `<text y="-${radius+margin+padding}" font-size="${fontSize}" font-family="sans-serif" text-anchor="middle" dy="0.4em">${angle}</text>`;
};
}
Insert cell
function repeat(component, N, initialAngle=0) {
// NOTE: if component is a function, it will be called with (angle, i)
if (N <= 0) return "";
let result = [];
for (let i = 0; i < N; i++) {
let angle = (360 / N) * i + initialAngle;
let el = typeof component === 'function'? component(angle, i) : component;
result.push(`<g transform="rotate(${angle})">${el}</g>`);
}
return result.join("");
}
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