Public
Edited
Jun 26, 2024
Importers
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
const width = 320;
const b = bar()
.chartWidth(width)
.marginLeft(90)
.marginRight(16)
.data([["Alice", 1], ["Bob", 2], ["Charlotte", 3]]);
const height = b.chartHeight();
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.call(b);

return svg.node();
}
Insert cell
bar = function(context){
let barHeight = 26,
barPadding = 10,
barColor = d => "#000",
marginLeft = 100,
marginRight = 10,
marginTop = 0,
marginBottom = 0,
value = d => d[1],
valueColor = d => "#000",
valueFormat = d => d,
label = d => d[0],
labelColor = d => "#000",
labelFormat = d => d,
data = [],
chartWidth = width;
function chart(context){
const innerWidth = chartWidth - marginLeft - marginRight,
innerHeight = chart.chartHeight() - marginTop - marginBottom;
const x = d3.scaleLinear()
.domain([0, d3.max(data, value)])
.range([0, innerWidth]);
const y = d3.scaleBand()
.domain(data.map(label))
.range([0, innerHeight]);
let g = context.select("g");
if (!g._groups[0][0]){
g = context.append("g");
}
g.attr("transform", `translate(${[marginLeft, marginTop]})`);
const rects = g.selectAll("rect")
.data(data)
.enter().append("rect")
.attr("width", d => x(value(d)))
.attr("height", barHeight)
.attr("y", d => y(label(d)))
.style("fill", barColor);
const labelText = g.selectAll(".label")
.data(data)
.enter().append("text")
.attr("class", "label")
.attr("x", -marginLeft)
.attr("y", d => y(label(d)))
.attr("dy", y.bandwidth() / 2)
.style("fill", labelColor)
.text((d, i, e) => labelFormat(label(d), i, e));
const valueText = g.selectAll(".value")
.data(data)
.enter().append("text")
.attr("class", "value")
.attr("x", d => x(value(d)))
.attr("y", d => y(label(d)))
.attr("dx", 5)
.attr("dy", y.bandwidth() / 2)
.style("fill", valueColor)
.text((d, i, e) => valueFormat(value(d), i, e));
}
chart.barHeight = _ => _ ? (barHeight = _, chart) : barHeight;
chart.barPadding = _ => _ ? (barPadding = _, chart) : barPadding;
chart.barColor = _ => _ ? (barColor = _, chart) : barColor;
chart.marginLeft = _ => _ ? (marginLeft = _, chart) : marginLeft;
chart.marginRight = _ => _ ? (marginRight = _, chart) : marginRight;
chart.marginTop = _ => _ ? (marginTop = _, chart) : marginTop;
chart.marginBottom = _ => _ ? (marginBottom = _, chart) : marginBottom;
chart.value = _ => _ ? (value = _, chart) : value;
chart.valueColor = _ => _ ? (valueColor = _, chart) : valueColor;
chart.valueFormat = _ => _ ? (valueFormat = _, chart) : valueFormat;
chart.label = _ => _ ? (label = _, chart) : label;
chart.labelColor = _ => _ ? (labelColor = _, chart) : labelColor;
chart.labelFormat = _ => _ ? (labelFormat = _, chart) : labelFormat;
chart.data = _ => _ ? (data = _, chart) : data;
chart.chartHeight = _ => barHeight * data.length + barPadding * (data.length - 2);
chart.chartWidth = _ => _ ? (chartWidth = _, chart) : chartWidth;
return chart;
}
Insert cell
beeswarm = context => {
let data = [],
chartWidth = width,
chartHeight = 100,
marginLeft = 10,
marginRight = 10,
marginTop = 10,
marginBottom = 17,
x = d => d[0],
xMin, xMax,
radius = d => 20,
radiusMax = 20,
padding = d => 1,
circleFill = d => "#000",
circleStroke = d => "#000",
tickValues, tickFormat,
forceTicks = 300;
function chart(context){
const innerWidth = chartWidth - marginLeft - marginRight;
const innerHeight = chartHeight - marginTop - marginBottom;
const xScale = chart.xScale();
const radiusScale = d3.scaleSqrt()
.domain(d3.extent(data, radius))
.range([0, radiusMax]);
const force = d3.forceSimulation(data)
.force("x", d3.forceX(d => xScale(x(d))))
.force("y", d3.forceY(innerHeight / 2))
.force("collide", d3.forceCollide(d => padding(d) + radiusScale(radius(d))))
.stop();
for (let i = 0; i < forceTicks; i++) force.tick();
let g = context.select("g");
if (!g._groups[0][0]){
g = context.append("g");
}
g.attr("transform", `translate(${[marginLeft, marginTop]})`);
const axis = d3.axisBottom(xScale);
if (tickValues){
axis.tickValues(tickValues);
}
if (tickFormat){
axis.tickFormat(tickFormat);
}
g.append("g")
.call(axis)
.attr("transform", `translate(0, ${innerHeight})`)
g.selectAll("circle")
.data(data)
.enter().append("circle")
.style("fill", circleFill)
.style("stroke", circleStroke)
.attr("cx", d => d.x)
.attr("cy", d => d.y)
.attr("r", d => radiusScale(radius(d)));
}
chart.data = _ => _ ? (data = _, chart) : data;
chart.chartWidth = _ => _ ? (chartWidth = _, chart) : chartWidth;
chart.chartHeight = _ => _ ? (chartHeight = _, chart) : chartHeight;
chart.marginLeft = _ => _ ? (marginLeft = _, chart) : marginLeft;
chart.marginRight = _ => _ ? (marginRight = _, chart) : marginRight;
chart.marginTop = _ => _ ? (marginTop = _, chart) : marginTop;
chart.marginBottom = _ => _ ? (marginBottom = _, chart) : marginBottom;
chart.x = _ => _ ? (x = _, chart) : x;
chart.xMax = _ => _ ? (xMax = _, chart) : xMax;
chart.xMin = _ => _ ? (xMin = _, chart) : xMin;
chart.radius = _ => _ ? (radius = _, chart) : radius;
chart.radiusMax = _ => _ ? (radiusMax = _, chart) : radiusMax;
chart.padding = _ => _ ? (padding = _, chart) : padding;
chart.circleFill = _ => _ ? (circleFill = _, chart) : circleFill;
chart.circleStroke = _ => _ ? (circleStroke = _, chart) : circleStroke;
chart.tickValues = _ => _ ? (tickValues = _, chart) : tickValues;
chart.tickFormat = _ => _ ? (tickFormat = _, chart) : tickFormat;
chart.forceTicks = _ => _ ? (forceTicks = _, chart) : forceTicks;
chart.xScale = _ => d3.scaleLinear()
.domain(xMin && xMax ? [xMin, xMax] : xMin ? [xMin, d3.max(data, x)] : xMax ? [d3.min(data, x), xMax] : d3.extent(data, x))
.range([0, chart.chartWidth() - chart.marginLeft() - chart.marginRight()]);
return chart;
}
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