Published
Edited
Feb 26, 2022
Insert cell
Insert cell
Insert cell
colorScale = d3.scaleOrdinal(
[...new Set(data.map((d) => d.species))],
d3.schemeTableau10
)
Insert cell
swatches({ color: colorScale })
Insert cell
chart = Plot.dot(data, {
x: "flipper_length",
y: "body_mass",
fill: "species",
title: "species"
}).plot({ grid: true })
Insert cell
Insert cell
addColorLegend(
Plot.dot(data, {
x: "flipper_length",
y: "body_mass",
fill: "species",
title: "species"
}).plot({
grid: true,
style: { paddingRight: 150, overflow: "visible" },
caption: "something something about penguins"
}),
colorScale
)
Insert cell
Insert cell
chart2 = addLegend(
Plot.dot(data, {
x: "flipper_length",
y: "body_mass",
fill: "species",
title: "species"
}).plot({ grid: true }),
colorLegend(colorScale)
)
Insert cell
Insert cell
function addLegend (chart, legend) {
let [lw, cw] = [+legend.getAttribute("width"), +chart.getAttribute("width")];
let [lh, ch] = [
+legend.getAttribute("height"),
+chart.getAttribute("height")
];
return svg`<svg width=${lw + cw} height=${Math.max(
lh,
ch
)}>${chart}<g transform=translate(${cw},0)>${legend}</g></svg>`;
}
Insert cell
function addColorLegend(
chart,
colorScale,
options = { sampleSize: 20, lineSpacing: 1.2, margin: 5, x0: 640, y0: 10 }
) {
const { sampleSize, lineSpacing, margin, x0, y0 } = options;
const leg = svg`<g style="font-family:sans-serif; font-size:x-small; ">`;
const domain = colorScale.domain();
const range = colorScale.range();
domain.forEach((label, i) => {
const x = x0;
const y = y0 + sampleSize * lineSpacing * i;
const group = svg`<g transform='translate(${x},${y})'>`;
leg.append(group);
group.append(
svg`<rect fill=${
range[i % range.length]
} width=${sampleSize} height=${sampleSize}>`
);
group.append(
svg`<text text-anchor=start dx=${sampleSize + margin} dy=${sampleSize *
0.7}>${label}</text>`
);
});
if (chart.nodeName === "svg") chart.append(leg);
else
d3.select(chart)
.select("svg")
.append(() => leg);
return chart;
}
Insert cell
function colorLegend(colorScale, options = {}) {
let { tickPadding = 5, width = 110, marginRight = 80 } = options;
return Plot.plot({
marks: [
Plot.cellX(colorScale.domain(), {
y: colorScale.domain(),
x: 0,
color: colorScale.range()
})
],
y: {
axis: "right",
tickSize: 0,
tickPadding
},
x: {
axis: null
},
width,
marginRight
});
}
Insert cell
import { data } from "@observablehq/plot-exploration-penguins"
Insert cell
import { swatches } from "@d3/color-legend"
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