Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/legends/swatches.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ function maybeScale(scale, key) {
return s;
}

function checkDomainMatch(scale, symbol) {
for (const d of symbol.domain) {
if (scale.scale(d) === undefined) throw new Error("the color and symbol scale domains must match");
}
}

export function legendSwatches(color, {opacity, ...options} = {}) {
if (!isOrdinalScale(color) && !isThresholdScale(color))
throw new Error(`swatches legend requires ordinal or threshold color scale (not ${color.type})`);
Expand Down Expand Up @@ -49,6 +55,8 @@ export function legendSymbols(
const [vs, cs] = maybeColorChannel(stroke);
const sf = maybeScale(scale, vf);
const ss = maybeScale(scale, vs);
if (vf === "color") checkDomainMatch(sf, symbol);
if (vs === "color") checkDomainMatch(ss, symbol);
const size = r * r * Math.PI;
fillOpacity = maybeNumberChannel(fillOpacity)[1];
strokeOpacity = maybeNumberChannel(strokeOpacity)[1];
Expand Down
23 changes: 23 additions & 0 deletions test/legend-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,26 @@ it("Plot.legend({}) throws an error", () => {
it("Plot.legend({color: {}}) throws an error", () => {
assert.throws(() => Plot.legend({color: {}}), /unknown legend type/);
});

it("Plot.legend({color, symbol}) throws an error when the color and symbol domains don't match", () => {
assert.throws(
() => Plot.legend({color: {domain: [1, 2, 3]}, symbol: {domain: [4, 5, 6]}}),
/the color and symbol scale domains must match/
);
});

it("Plot.legend({color, symbol}) applies the color scale to the symbol stroke when the domains match", () => {
const legend = Plot.legend({color: {domain: [1, 2, 3]}, symbol: {domain: [1, 2, 3]}});
const strokes = [...legend.querySelectorAll("svg")].map((svg) => svg.getAttribute("stroke"));
assert.deepStrictEqual(strokes, ["#4269d0", "#efb118", "#ff725c"]);
});

it("Plot.legend({color, symbol}) applies the color scale to the symbol stroke when the color domain is a superset", () => {
const legend = Plot.legend({color: {domain: [1, 2, 3, 4]}, symbol: {domain: [1, 2, 3]}});
const strokes = [...legend.querySelectorAll("svg")].map((svg) => svg.getAttribute("stroke"));
assert.deepStrictEqual(strokes, ["#4269d0", "#efb118", "#ff725c"]);
});

it("Plot.legend({symbol}) does not throw when there is no color scale", () => {
assert.doesNotThrow(() => Plot.legend({symbol: {domain: [1, 2, 3]}}));
});