Public
Edited
Nov 7, 2023
Insert cell
Insert cell
vis = html`<div class="vis-cc"></div>`
Insert cell
concentricPctLines(value, {
bind: d3.select(vis), // pass in the selection
modulus: 5, // i.e each circle is 5%
scaleSqrt: scaleToggle
})
Insert cell
Insert cell
Insert cell
function concentricPctLines (datum, {
bind = null, // pass in a d3 selection i.e d3.select('class/div')
margin = {top: 10, right: 10, bottom: 30, left: 10},
circleSize = 100,
width = (circleSize * 2) + (margin.left + margin.right),
height = circleSize * 1.8 + (margin.top + margin.bottom),
modulus = 5, // what % each circle represents
col = {
active: '#1b3644',
passive: '#ffa6d9'
},
strokeWidth = 1,
domain = [0, 100],
range = [0, circleSize],
scaleSqrt = true // if to use scaleSqrt scale or even distribution
} = {}) {

// set the dimensions and margins of the graph
const w = width - margin.left - margin.right
const h = height - margin.top - margin.bottom
bind.selectAll('svg').remove();
const sel = bind.append('svg')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);

const scale = (scaleSqrt)? d3.scaleSqrt() : d3.scaleLinear();
scale.domain(domain).range(range);

const r = scale(circleSize); // radius of full circle
const translate = `translate(${width / 2},${(height - margin.bottom) / 2 })`;

const passive = sel.append('g')
.attr('class', 'g-passive-wrap')
.attr('transform', translate);

const active = sel.append('g')
.attr('class', 'g-active-wrap')
.attr('transform', translate);

// passive (background) circle(s)
passive.selectAll('circle')
.data(d3.range(domain[1]))
.join('circle')
.attr('r', d => {
if ((d % modulus) == 0){
return scale(d + 1)
} else {
return 0
}
})
.attr('fill', 'transparent')
.attr('stroke', col.passive)
.style('opacity', 0.4)
.attr('stroke-width', strokeWidth);

// active circle(s)
active.selectAll('circle')
.data(d3.range(datum))
.join('circle')
.attr('r', d => {
if ((d % modulus) == 0){
return scale(d + 1)
} else {
return 0
}
})
.attr('fill', 'transparent')
.attr('stroke', col.active)
.attr('stroke-width', strokeWidth);
// show pct
active.append('text')
.attr('class', 'percent-label')
.attr('y', r)
.attr('dy', 15)
.style('text-anchor', 'middle')
.text(datum + '%');

return sel;

}
Insert cell
Insert cell
Insert cell
Insert cell
visWrap = html`<div class="vis-1 flex flex-wrap "></div>`
Insert cell
[30, 45, 25, 80, 60, 5, 20, 25, 15, 10, 90, 50].forEach((d, i) => {
const div = d3.select(visWrap).append('div').attr('class', 'ref-' + i)
concentricPctLines(d, {
bind: d3.select(visWrap).select('.ref-' + i),
margin: {top: 30, right: 30, bottom: 50, left: 10},
modulus: 5, // i.e each circle is 5%
scaleSqrt: scaleToggle,
col: {
active: '#ed3d66',
passive: '#33ff7d'
}
})
})
Insert cell
<hr>
<link href="https://fonts.googleapis.com/css?family=Space+Mono" rel="stylesheet">
<link href="https://unpkg.com/basscss@8.0.2/css/basscss.min.css" rel="stylesheet">
<style>
text {
font-family:'Space Mono',monospace;
fill: #130C0E;
font-size: 11px;
}
</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