Public
Edited
Feb 23, 2024
4 stars
Also listed in…
HR
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function renderTeam (data, {
imageSize = 100, //square
columnLength = null,
bgdCol = '#abf5ed',
strokeCol = '#202d85',
strokeWidth = 6,
textBoxheight = 30
} = {}) {

const dataLength = data.length
const size = (imageSize + (strokeWidth * 2))
const columns = (columnLength !== null && columnLength > 1 ) ? columnLength : Math.floor(width / size)
const rows = Math.ceil((dataLength / columns))
const height = rows * (size + textBoxheight)

const svg = d3.create('svg')
.attr('width', width)
.attr('height', height + strokeWidth)

renderDefs(data)

function renderDefs (data) {
const defs = svg.append('defs')
.selectAll('pattern')
.data(data)
.join('pattern')
.attr('id', d => `p-${d.id}`)
.attr('width', 1)
.attr('height', 1)
.append('image')
.attr('xlink:href', d => `https://api.dicebear.com/7.x/avataaars/svg?seed=${d.name}`)
.attr('x', 5)
.attr('y', 0)
.attr('width', size)
.attr('height', size)
}

const scaleColumn = d3.scaleLinear()
.domain([0, columns])
.range([strokeWidth/2, columns * size])

const scaleRow = d3.scaleLinear()
.domain([0, rows])
.range([strokeWidth/2, height + strokeWidth/2])
const g = svg
.selectAll('g')
.data(data)
.join('g')
.attr('class', 'item')
// .attr('transform', (d, i) => `translate(${i * size + 3}, ${size})`)
.attr('transform', (d, i) => {
const x = i % columns
const y = Math.floor(i / columns)
return `translate(${scaleColumn(x)}, ${scaleRow(y)})`
})


g.append('rect')
.attr('width', size)
.attr('height', size + textBoxheight)
.attr('stroke', strokeCol)
.attr('stroke-width', strokeWidth)
.attr('class', 'item-bgd')
.attr('fill', bgdCol)

g.append('rect')
.attr('width', size)
.attr('height', size)
.attr('class', 'item-img')
.attr('fill', d => {
const id = `p-${d.id}`
return `url(#${id})`
})

g.append('text')
.attr('x', size/2)
.attr('y', size)
.attr('dy', '20px')
.text(d => d.name)

return svg.node()
}
Insert cell
Insert cell
Insert cell
teamData = {

const teamSizes = [20, 15, 10, 10, 8, 6, 3, 3, 2]
const teamNames = teamSizes.map((d, i) => `t-0${i + 1}`)

let teamIndex = 0 // use as a refernce to change team
let teamChange = teamSizes[teamIndex]
const members = d3.range(_.sum(teamSizes)).map((d, i) => {
if (i >= teamChange) {
teamIndex++
teamChange = teamChange + teamSizes[teamIndex]
}
return {
name: names[_.random(0, 328)],
team: teamNames[teamIndex],
los_months: _.sample([_.random(1, 30), _.random(1, 30), _.random(0, 50), _.random(1, 200)]),
id: i,
img: `${i}.svg` // return a unique id!
}
})

return members
}
Insert cell
Insert cell
_.uniqBy(teamData, 'team').map(d => d.team)
Insert cell
Insert cell
Insert cell
<hr>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=PT+Sans&display=swap" rel="stylesheet">

<style>
text {
font-family: 'PT Sans', sans-serif;
font-weight: 400;
font-size: 9px;
letter-spacing: 2px;
text-anchor: middle;
}


</style>

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