Public
Edited
Sep 5, 2023
2 forks
Importers
2 stars
Insert cell
Insert cell
vis = html`<div class="vis-cc"></div>`
Insert cell
waffle(value, {
bind: d3.select(vis), // pass in the selection
activeFill: '#3dbd5d'
})
Insert cell
Insert cell
visSquare = html`<div class="vis-cc-square"></div>`
Insert cell
waffle(value, {
bind: d3.select(visSquare), // pass in the selection
activeFill: '#de4500',
passiveFill: '#ebd999',
shape: 'rect'
})
Insert cell
function waffle (value = 90, {
bind = null, // pass in a d3 selection i.e d3.select('class/div')
shape = 'circle', // 'circle' 'rect'
activeFill = '#008cbc', // colour of the square or circle
passiveFill = '#e5e7de', // when there is no value
strokeCol = '#666666',
shapeSize = 15,
strokeWidth = 0,
margin = {
top: shapeSize,
right: shapeSize,
bottom: shapeSize,
left: shapeSize,
}
} = {}) {

const size = (shapeSize + (strokeWidth * 2)) * 10

// append the svg if first render
if (bind.select('svg').empty()) {
bind
.append('svg')
.attr('width', size + margin.left + margin.right)
.attr('height', size + margin.top + margin.bottom)
.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`)
.call(grid10by10)
}

function grid10by10 (sel) {
const scaleX = d3.scaleLinear()
.domain([0, 9])
.range([0, shapeSize * 10])

const scaleY = d3.scaleLinear()
.domain([0, 9])
.range([shapeSize * 10, 0])

const render = sel.selectAll(shape)
.data(d3.range(100))
.join(shape)
.attr('stroke-width', strokeWidth)
.attr('stroke', strokeCol)
// note < not <= as counting from 0
.attr('fill', (d, i) => (i < value) ? activeFill : passiveFill)

if (shape === 'rect') {
render
.attr('x', (d, i) => {
const n = i % 10
return scaleX(n)
})
.attr('y', (d, i) => {
const n = Math.floor(i / 10)
return scaleY(n)
})
.attr('width', shapeSize)
.attr('height', shapeSize)
} else {
render
.attr('cx', (d, i) => {
const n = i % 10
return scaleX(n)
})
.attr('cy', (d, i) => {
const n = Math.floor(i / 10)
return scaleY(n)
}).attr('r', shapeSize / 2)
}
}

return bind.select('svg g').call(grid10by10)

}
Insert cell
Insert cell
Insert cell
visWrap = html`<div class="vis-1 flex flex-wrap "></div>`
Insert cell
{ // have a way of updating the cell put not creating extra dom elements
if (d3.select(visWrap).empty()) { // don't reload on any cell refreshes
testMultipleRender(visWrap);
} else {
d3.select(visWrap).selectAll('div').remove();
testMultipleRender(visWrap);
}
}
Insert cell
viewof activeFill = Inputs.color({label: "Active fill:", value: "#505423"})
Insert cell
viewof passiveFill = Inputs.color({label: "Passive fill:", value: "#eeeeee"})
Insert cell
function testMultipleRender(sel, col) { // render dom and bind svg visual to it
return [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)
d3.select('.ref-' + i).selectAll('h3').remove(); // tidy for refreshes on page
d3.select('.ref-' + i).append('h3').attr('class', 'label').text(d + '%')
waffle(d, {
bind: d3.select('.ref-' + i),
activeFill: activeFill,
passiveFill: passiveFill,
})
})
}
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>
.label {
font-family:'Space Mono',monospace;
color: #008cbc;
font-size: 13px;
padding-left: 5px;
}
</style>
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more