Skip to content

Commit 6bea18e

Browse files
authored
handle degenerate domains (#2212)
1 parent ff7d83c commit 6bea18e

7 files changed

+124
-6
lines changed

src/scales.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -425,10 +425,11 @@ function inferScaleType(key, channels, {type, domain, range, scheme, pivot, proj
425425
if (kind === opacity || kind === length) return "linear";
426426
if (kind === symbol) return "ordinal";
427427

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

433434
// Otherwise, infer the scale type from the data! Prefer the domain, if
434435
// present, over channels. (The domain and channels should be consistently

src/scales/quantitative.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ export function createScaleQ(
8080
reverse
8181
}
8282
) {
83+
domain = maybeRepeat(domain);
8384
interval = maybeRangeInterval(interval, type);
8485
if (type === "cyclical" || type === "sequential") type = "linear"; // shorthand for color schemes
8586
if (typeof interpolate !== "function") interpolate = maybeInterpolator(interpolate); // named interpolator
@@ -88,8 +89,8 @@ export function createScaleQ(
8889
// If an explicit range is specified, and it has a different length than the
8990
// domain, then redistribute the range using a piecewise interpolator.
9091
if (range !== undefined) {
91-
const n = (domain = arrayify(domain)).length;
92-
const m = (range = arrayify(range)).length;
92+
const n = domain.length;
93+
const m = (range = maybeRepeat(range)).length;
9394
if (n !== m) {
9495
if (interpolate.length === 1) throw new Error("invalid piecewise interpolator"); // e.g., turbo
9596
interpolate = piecewise(interpolate, range);
@@ -137,6 +138,11 @@ export function createScaleQ(
137138
return {type, domain, range, scale, interpolate, interval};
138139
}
139140

141+
function maybeRepeat(values) {
142+
values = arrayify(values);
143+
return values.length >= 2 ? values : [values[0], values[0]];
144+
}
145+
140146
function maybeNice(nice, type) {
141147
return nice === true ? undefined : typeof nice === "number" ? nice : maybeNiceInterval(nice, type);
142148
}
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<div class="plot-swatches plot-swatches-wrap">
2+
<style>
3+
:where(.plot-swatches) {
4+
font-family: system-ui, sans-serif;
5+
font-size: 10px;
6+
margin-bottom: 0.5em;
7+
}
8+
9+
:where(.plot-swatch > svg) {
10+
margin-right: 0.5em;
11+
overflow: visible;
12+
}
13+
14+
:where(.plot-swatches-wrap) {
15+
display: flex;
16+
align-items: center;
17+
min-height: 33px;
18+
flex-wrap: wrap;
19+
}
20+
21+
:where(.plot-swatches-wrap .plot-swatch) {
22+
display: inline-flex;
23+
align-items: center;
24+
margin-right: 1em;
25+
}
26+
</style>
27+
</div>
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<div class="plot-swatches plot-swatches-wrap">
2+
<style>
3+
:where(.plot-swatches) {
4+
font-family: system-ui, sans-serif;
5+
font-size: 10px;
6+
margin-bottom: 0.5em;
7+
}
8+
9+
:where(.plot-swatch > svg) {
10+
margin-right: 0.5em;
11+
overflow: visible;
12+
}
13+
14+
:where(.plot-swatches-wrap) {
15+
display: flex;
16+
align-items: center;
17+
min-height: 33px;
18+
flex-wrap: wrap;
19+
}
20+
21+
:where(.plot-swatches-wrap .plot-swatch) {
22+
display: inline-flex;
23+
align-items: center;
24+
margin-right: 1em;
25+
}
26+
</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">
27+
<rect width="100%" height="100%"></rect>
28+
</svg>0</span>
29+
</div>
Loading
Loading

test/plots/legend-color.ts

+16
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,22 @@ export function colorLegendCategoricalReverse() {
3434
return Plot.legend({color: {domain: "ABCDEFGHIJ", reverse: true}});
3535
}
3636

37+
export function colorLegendDomainUnary() {
38+
return Plot.legend({color: {domain: [0]}});
39+
}
40+
41+
export function colorLegendDomainEmpty() {
42+
return Plot.legend({color: {domain: []}});
43+
}
44+
45+
export function colorLegendLinearDomainUnary() {
46+
return Plot.legend({color: {type: "linear", domain: [0]}});
47+
}
48+
49+
export function colorLegendLinearDomainEmpty() {
50+
return Plot.legend({color: {type: "linear", domain: []}});
51+
}
52+
3753
export function colorLegendOrdinal() {
3854
return Plot.legend({color: {type: "ordinal", domain: "ABCDEFGHIJ"}});
3955
}

0 commit comments

Comments
 (0)