Skip to content

Commit

Permalink
handle degenerate domains
Browse files Browse the repository at this point in the history
  • Loading branch information
mbostock committed Nov 19, 2024
1 parent 700c6ee commit 9da8083
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 6 deletions.
9 changes: 5 additions & 4 deletions src/scales.js
Original file line number Diff line number Diff line change
Expand Up @@ -425,10 +425,11 @@ function inferScaleType(key, channels, {type, domain, range, scheme, pivot, proj
if (kind === opacity || kind === length) return "linear";
if (kind === symbol) return "ordinal";

// If the domain or range has more than two values, assume it’s ordinal. You
// can still use a “piecewise” (or “polylinear”) scale, but you must set the
// type explicitly.
if ((domain || range || []).length > 2) return asOrdinalType(kind);
// If a domain or range is explicitly specified and doesn’t have two values,
// assume it’s ordinal. You can still use a “piecewise” (or “polylinear”)
// scale, but you must set the type explicitly.
const n = (domain ?? range)?.length;
if (n < 2 || n > 2) return asOrdinalType(kind);

// Otherwise, infer the scale type from the data! Prefer the domain, if
// present, over channels. (The domain and channels should be consistently
Expand Down
10 changes: 8 additions & 2 deletions src/scales/quantitative.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export function createScaleQ(
reverse
}
) {
domain = maybeRepeat(domain);
interval = maybeRangeInterval(interval, type);
if (type === "cyclical" || type === "sequential") type = "linear"; // shorthand for color schemes
if (typeof interpolate !== "function") interpolate = maybeInterpolator(interpolate); // named interpolator
Expand All @@ -88,8 +89,8 @@ export function createScaleQ(
// If an explicit range is specified, and it has a different length than the
// domain, then redistribute the range using a piecewise interpolator.
if (range !== undefined) {
const n = (domain = arrayify(domain)).length;
const m = (range = arrayify(range)).length;
const n = domain.length;
const m = (range = maybeRepeat(range)).length;
if (n !== m) {
if (interpolate.length === 1) throw new Error("invalid piecewise interpolator"); // e.g., turbo
interpolate = piecewise(interpolate, range);
Expand Down Expand Up @@ -137,6 +138,11 @@ export function createScaleQ(
return {type, domain, range, scale, interpolate, interval};
}

function maybeRepeat(values) {
values = arrayify(values);
return values.length >= 2 ? values : [values[0], values[0]];
}

function maybeNice(nice, type) {
return nice === true ? undefined : typeof nice === "number" ? nice : maybeNiceInterval(nice, type);
}
Expand Down
27 changes: 27 additions & 0 deletions test/output/colorLegendDomainEmpty.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<div class="plot-swatches plot-swatches-wrap">
<style>
:where(.plot-swatches) {
font-family: system-ui, sans-serif;
font-size: 10px;
margin-bottom: 0.5em;
}

:where(.plot-swatch > svg) {
margin-right: 0.5em;
overflow: visible;
}

:where(.plot-swatches-wrap) {
display: flex;
align-items: center;
min-height: 33px;
flex-wrap: wrap;
}

:where(.plot-swatches-wrap .plot-swatch) {
display: inline-flex;
align-items: center;
margin-right: 1em;
}
</style>
</div>
29 changes: 29 additions & 0 deletions test/output/colorLegendDomainUnary.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<div class="plot-swatches plot-swatches-wrap">
<style>
:where(.plot-swatches) {
font-family: system-ui, sans-serif;
font-size: 10px;
margin-bottom: 0.5em;
}

:where(.plot-swatch > svg) {
margin-right: 0.5em;
overflow: visible;
}

:where(.plot-swatches-wrap) {
display: flex;
align-items: center;
min-height: 33px;
flex-wrap: wrap;
}

:where(.plot-swatches-wrap .plot-swatch) {
display: inline-flex;
align-items: center;
margin-right: 1em;
}
</style><span class="plot-swatch"><svg width="15" height="15" fill="#4269d0" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<rect width="100%" height="100%"></rect>
</svg>0</span>
</div>
17 changes: 17 additions & 0 deletions test/output/colorLegendLinearDomainEmpty.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 22 additions & 0 deletions test/output/colorLegendLinearDomainUnary.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions test/plots/legend-color.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,22 @@ export function colorLegendCategoricalReverse() {
return Plot.legend({color: {domain: "ABCDEFGHIJ", reverse: true}});
}

export function colorLegendDomainUnary() {
return Plot.legend({color: {domain: [0]}});
}

export function colorLegendDomainEmpty() {
return Plot.legend({color: {domain: []}});
}

export function colorLegendLinearDomainUnary() {
return Plot.legend({color: {type: "linear", domain: [0]}});
}

export function colorLegendLinearDomainEmpty() {
return Plot.legend({color: {type: "linear", domain: []}});
}

export function colorLegendOrdinal() {
return Plot.legend({color: {type: "ordinal", domain: "ABCDEFGHIJ"}});
}
Expand Down

0 comments on commit 9da8083

Please sign in to comment.