Published
Edited
Sep 28, 2019
Insert cell
Insert cell
visual = {
const svg = d3
.select(DOM.svg(w, h))
.style('background', '#16324F')
.style('width', w)
.style('height', h)
const oribtsGroup = svg.append('g')
.attr('stroke-width', 1)
.attr('fill', '#426578')
.attr('stroke', '#426578')
const planetsGroup = svg.append('g')
.attr('stroke-width', 1)
.attr('stroke', '#16324F')
.attr('fill', '#16324F')
.attr('fill-opacity', 1)
const defs = svg.append('svg:defs')
defs.selectAll('.planet')
.data(names)
.enter()
.append("svg:pattern")
.attr('id', (d) => d.toLowerCase().replace(' ', '-'))
.attr('width', '100%')
.attr('height', '100%')
.attr('patternContentUnits', 'objectBoundingBox')
.append('svg:image')
.attr('preserveAspectRatio', 'none')
.attr('xlink:href', (d) => `https://i.pravatar.cc/150?u=${d}`)
.attr('width', 1)
.attr('height', 1)
//.attr('x', 0)
//.attr('y', 0)

draw(oribtsGroup, planetsGroup)
svg.call(d3.zoom()
.scaleExtent([0, 1])
.translateExtent([[0, 0], [w, h]])
.on('zoom', zoomed))

function zoomed() {
oribtsGroup.attr('transform', d3.event.transform)
planetsGroup.attr('transform', d3.event.transform)
}
return svg.node()
}
Insert cell
function draw(orbits, planets) {
const TAU = 2 * Math.PI
const radius = h/8
const center = { x: w/2, y: h/2 }
for (let i = 1; i <= c; i++) {
const r = radius * Math.pow(i, 3)
const l = 1 * Math.pow(i, 2)
const o = i === 1 ? 1 : 0
// Shadows
orbits.append('circle')
.attr('r', r)
.attr('stroke-width', l * 4)
.attr('stroke', '#18435A')
.attr('fill-opacity', 0)
.attr('cx', center.x)
.attr('cy', center.y)
// Orbits
orbits.append('circle')
.attr('r', r)
.attr('stroke-width', l)
.attr('fill-opacity', o)
.attr('cx', center.x)
.attr('cy', center.y)
if (i === 1) continue
const radians = Math.random() * TAU
const max = Math.floor(Math.random() * m)
for(let j = 1; j <= max; j++) {
// Planets
//const x = center.x + Math.sin(radians) * r
//const y = center.y + Math.cos(radians) * r
const cx = Math.sin(radians + TAU / max * j) * r + center.x
const cy = Math.cos(radians + TAU / max * j) * r + center.y
const pr = 30 * l
const avatar = names[Math.floor(Math.random() * names.length)].toLowerCase().replace(' ', '-')
// shadow
/*
planets.append('circle')
.attr('r', r * 0.05 * 1.1)
.attr('cx', cx)
.attr('cy', cy)
.attr('fill', '#EFEFD0')
*/
// Inner
planets.append('circle')
.attr('class', 'planet')
.attr('r', 30 * l)
.attr('cx', cx)
.attr('cy', cy)
.attr('stroke-width', l * 5)
.style('fill', '#16324F')
.style('fill', () => `url(#${avatar})`)
.on('mouseover', function() {
d3.select(this)
.transition(300)
.attr('cursor', 'pointer')
.attr('r', pr * 1.8)
})
.on('mouseout', function() {
d3.select(this)
.transition(300)
.attr('r', pr)
})
}
}

}
Insert cell
Insert cell
// amount of outlines
c = 20
Insert cell
Insert cell
Insert cell
Insert cell
names = [
'Tevin Sharma',
'Jenny Malone',
'Ivo Koch',
'Gary Davey',
'Samera Wells',
'Lacy May',
'Freyja Wheeler',
'Husna Muir',
'Alfred Frank',
'Amanda Manning',
'Gurpreet Phan',
'Macaulay Stewart',
'Zakir Odonnell',
'Bibi Conner',
'Karina Soto',
'Kim Best',
'Mehdi Vickers',
'Kay Wang',
'Zahraa Prince',
'Haider Legge',
'Safiyyah Irving',
'Raul Pollard',
'Ahmed Hanson',
'Marni Obrien',
'Rojin Gaines',
'Zeynep Whitaker',
'Cayden Mccabe',
'Nicky Redfern',
'Glenn Potts',
'Christie Handley',
'Eliot Firth',
'Stefania Mcmahon',
'Lachlan Garza',
'Brooklyn Vaughn',
'Edward Delaney',
'Alima Humphrey',
'Bernard Hirst',
'Asia Martin',
'Elli Traynor',
'Nettie Burke',
'Faris Barron',
'Thea Bob',
'Gracie-Leigh Silva',
'Keyaan Valenzuela',
'Keith Mohammed',
'Zuzanna William',
'Caitlin Anthony',
'Louisa Hackett',
'Keeva Townsend',
'Agatha Philip',
'Bridget Schmidt',
'Elodie Sims',
'Eduardo Cassidy',
'Ubaid Jackson',
'Susie Christie',
'Kobie Klein',
'Lochlan Lovell',
'Debbie Forbes',
'Linda Dodd',
]
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