Published
Edited
Dec 13, 2019
Importers
36 stars
Insert cell
Insert cell
Insert cell
html`<svg viewBox="0 0 ${size} ${size}">${timesTable.map((arr, i) =>
draw(
arr,
size / cols / 2,
`translate(${(i % cols) * (size / (cols * 2)) * 2 +
size / (cols * 2)}, ${(Math.floor(i / cols) * size) / cols +
size / (cols * 2)})`
)
)}</svg>`
Insert cell
Insert cell
size = cols * 96 * 2
Insert cell
cols = 12
Insert cell
Insert cell
fromStIves = html`<svg viewBox="0 0 1200 1200">${[
draw([7], 300, `translate(300, 300)`),
draw([7, 7], 300, `translate(900, 300)`),
draw([7, 7, 7], 300, `translate(300, 900)`),
draw([7, 7, 7, 7], 300, `translate(900, 900)`)
]}</svg>`
Insert cell
md`## 2 x 3 x 5 x 7
Prime multiplication, with different sorting`
Insert cell
primes = html`<svg viewBox="0 0 1200 1200">${[
draw([7, 5, 3, 2], 300, `translate(300, 300)`),
draw([5, 3, 2, 7], 300, `translate(900, 300)`),
draw([3, 2, 7, 5], 300, `translate(300, 900)`),
draw([2, 7, 5, 3], 300, `translate(900, 900)`)
]}</svg>`
Insert cell
md`## 3^8`
Insert cell
sierp = html`<svg viewBox="0 0 1200 1200">${[
draw([3, 3, 3, 3, 3, 3, 3, 3], 600, `translate(600, 600)`)
]}</svg>`
Insert cell
Insert cell
function draw(arr, radius, transform) {
const cloned = arr.slice();
const n = cloned.shift();
let packing;
if (n) {
packing = packings[n - 1];
if (packing.primes) {
const primesClone = [...packing.primes, ...cloned];
return draw(primesClone, radius, transform);
}
}
return svg`
<g title="${arr.join('*')}" transform="${transform}">
<circle r=${radius} fill=none stroke=${
arr.length === 0 ? 'black' : 'pink'
} />
${
n && packing
? Array(n)
.fill(0)
.map((_, i) => {
const nextRadius = radius / packing.r;
return draw(
cloned,
nextRadius,
packing.transforms(radius, nextRadius, i)
);
})
: ''
}
</g>`;
}
Insert cell
// https://en.wikipedia.org/wiki/Circle_packing_in_a_circle
// Approximate
packings = {
const regularTransform = n => (outerRadius, radius, i) =>
`rotate(${(360 / n) * i}) translate(0, ${radius - outerRadius})`;
const transform7 = (outerRadius, radius, i) =>
i < 6 ? regularTransform(6)(outerRadius, radius, i) : `translate(0, 0)`;
// Not exact
const transform11 = (outerRadius, radius, i) =>
i < 8
? `rotate(${(360 / 9) * i - (360 / 9) * 3.5}) translate(0, ${radius -
outerRadius})`
: `translate(0, ${radius * 0.4}) rotate(${(360 / 3) * i -
180}) translate(0, ${0 - radius * 1.155})`;
return [
{ count: 1, r: 1, transforms: regularTransform(1) },
{ count: 2, r: 2, transforms: regularTransform(2) },
{ count: 3, r: 2.154, transforms: regularTransform(3) },
{ count: 4, primes: [2, 2] },
{ count: 5, r: 2.701, transforms: regularTransform(5) },
{ count: 6, primes: [3, 2] },
{ count: 7, r: 3, transforms: transform7 },
{ count: 8, primes: [2, 2, 2] },
{ count: 9, primes: [3, 3] },
{ count: 10, primes: [5, 2] },
{ count: 11, r: 3.923, transforms: transform11 },
{ count: 12, primes: [3, 2, 2] }
];
}
Insert cell
elevens = html`<svg viewBox="0 0 1200 400">${[
draw([11], 200, `translate(200, 200)`),
draw([11, 11], 200, `translate(600, 200)`),
draw([11, 11, 11], 200, `translate(1000, 200)`)
]}</svg>`
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