diff --git a/src/options.js b/src/options.js index 51043a854e..baaf4cad7a 100644 --- a/src/options.js +++ b/src/options.js @@ -280,6 +280,7 @@ export function maybeTuple(x, y) { export function maybeZ({z, fill, stroke} = {}) { if (z === undefined) [z] = maybeColorChannel(fill); if (z === undefined) [z] = maybeColorChannel(stroke); + if (isOptions(z)) z = z.value; return z; } diff --git a/test/output/zValueSelect.svg b/test/output/zValueSelect.svg new file mode 100644 index 0000000000..28f22f17cb --- /dev/null +++ b/test/output/zValueSelect.svg @@ -0,0 +1,70 @@ + + + + + 0.5 + 1.0 + 1.5 + 2.0 + 2.5 + 3.0 + + + ↑ y + + + + 0 + 5 + 10 + 15 + 20 + 25 + + + x → + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/output/zValueStack.svg b/test/output/zValueStack.svg new file mode 100644 index 0000000000..c4ec9f9b3c --- /dev/null +++ b/test/output/zValueStack.svg @@ -0,0 +1,84 @@ + + + + + 0 + 2 + 4 + 6 + 8 + 10 + 12 + 14 + 16 + 18 + 20 + 22 + 24 + 26 + 28 + 30 + + + ↑ value + + + + Apr + Feb + Jan + Mar + + + month + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/output/zValueWindow.svg b/test/output/zValueWindow.svg new file mode 100644 index 0000000000..644bd103f8 --- /dev/null +++ b/test/output/zValueWindow.svg @@ -0,0 +1,513 @@ + + + + + + 500 + 1,000 + 1,500 + 2,000 + 2,500 + 3,000 + 3,500 + + + ↑ value + + + + Jan2024 + Feb + Mar + Apr + May + Jun + Jul + Aug + Sep + Oct + Nov + Dec + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plots/z-value.ts b/test/plots/z-value.ts new file mode 100644 index 0000000000..01d27fcabd --- /dev/null +++ b/test/plots/z-value.ts @@ -0,0 +1,57 @@ +// Tests that z specified as {value} is unwrapped correctly by transforms. +// See https://github.com/observablehq/plot/issues/2271 + +import * as Plot from "@observablehq/plot"; +import * as d3 from "d3"; +import {test} from "test/plot"; + +test(async function zValueWindow() { + const random = d3.randomLcg(42); + const data = d3.sort( + ["a", "b", "c"].flatMap((type, i) => + d3.utcDay + .range(new Date("2024-01-01"), new Date("2025-01-01"), [1, 7, 30][i]) + .map((date) => ({type, date, value: ((random() * 1000) | 0) + i * 1500})) + ), + (d) => d.date + ); + return Plot.plot({ + y: {grid: true}, + marks: [ + Plot.dot(data, {x: "date", y: "value", fill: "type", r: 1.5}), + Plot.lineY( + data, + Plot.windowY({x: "date", y: "value", stroke: {value: "type"}, k: 10, reduce: "mean", anchor: "end"}) + ) + ] + }); +}); + +test(function zValueStack() { + const data = [ + {month: "Jan", revenue: 10, cost: 3, profit: 7}, + {month: "Feb", revenue: 12, cost: 4, profit: 8}, + {month: "Mar", revenue: 15, cost: 5, profit: 10}, + {month: "Apr", revenue: 11, cost: 6, profit: 5} + ].flatMap((d) => [ + {month: d.month, value: d.revenue, type: "revenue"}, + {month: d.month, value: d.cost, type: "cost"}, + {month: d.month, value: d.profit, type: "profit"} + ]); + return Plot.barY(data, Plot.stackY({x: "month", y: "value", fill: {value: "type"}, order: "sum"})).plot({ + color: {domain: ["cost", "profit", "revenue"]} + }); +}); + +test(async function zValueSelect() { + const random = d3.randomLcg(42); + const series = ["alpha", "bravo", "charlie", "delta", "echo", "foxtrot"]; + const data = series.flatMap((s, k) => d3.range(30).map((i) => ({x: i, y: random() + k * 0.5, series: s}))); + return Plot.plot({ + color: {scheme: "spectral"}, + marks: [ + Plot.line(data, {x: "x", y: "y", stroke: {value: "series"}, strokeOpacity: 0.5}), + Plot.dot(data, Plot.selectMaxY({x: "x", y: "y", fill: {value: "series"}, r: 4, stroke: "white"})) + ] + }); +});