diff --git a/src/transforms/bin.js b/src/transforms/bin.js index 02321a3345..5b31e74bda 100644 --- a/src/transforms/bin.js +++ b/src/transforms/bin.js @@ -67,22 +67,22 @@ export function bin(outputs = {fill: "count"}, options = {}) { return binn(x, y, null, null, outputs, maybeInsetX(maybeInsetY(options))); } -function maybeDenseInterval(bin, k, options = {}) { +function maybeDenseInterval(bin, x, y, options) { if (options?.interval == null) return options; const {reduce = reduceFirst} = options; - const outputs = {filter: null}; - if (options[k] != null) outputs[k] = reduce; - if (options[`${k}1`] != null) outputs[`${k}1`] = reduce; - if (options[`${k}2`] != null) outputs[`${k}2`] = reduce; + const outputs = {filter: null, [x]: `${x}1`}; + if (options[y] != null) outputs[y] = reduce; + if (options[`${y}1`] != null) outputs[`${y}1`] = reduce; + if (options[`${y}2`] != null) outputs[`${y}2`] = reduce; return bin(outputs, options); } export function maybeDenseIntervalX(options = {}) { - return maybeDenseInterval(binX, "y", withTip(options, "x")); + return maybeDenseInterval(binX, "x", "y", withTip(options, "x")); } export function maybeDenseIntervalY(options = {}) { - return maybeDenseInterval(binY, "x", withTip(options, "y")); + return maybeDenseInterval(binY, "y", "x", withTip(options, "y")); } function binn( diff --git a/test/output/aaplInterval.svg b/test/output/aaplInterval.svg index 0a058a34e0..5e76b5099f 100644 --- a/test/output/aaplInterval.svg +++ b/test/output/aaplInterval.svg @@ -36,16 +36,16 @@ 72 - Jun2013 - Jul - Aug - Sep + Jun2013 + Jul + Aug + Sep diff --git a/test/output/availability.svg b/test/output/availability.svg index 0e552df66c..42fa1b9c8f 100644 --- a/test/output/availability.svg +++ b/test/output/availability.svg @@ -33,20 +33,20 @@ ↑ value - Jan2020 - Apr - Jul - Oct - Jan2021 - Apr + Jan2020 + Apr + Jul + Oct + Jan2021 + Apr diff --git a/test/output/downloads.svg b/test/output/downloads.svg index 5d36dcdcf5..a763b3fd9f 100644 --- a/test/output/downloads.svg +++ b/test/output/downloads.svg @@ -47,18 +47,18 @@ ↑ downloads - 2018 - 2019 - 2020 - 2021 - 2022 + 2018 + 2019 + 2020 + 2021 + 2022 diff --git a/test/output/integerIntervalArea.html b/test/output/integerIntervalArea.html index 762c0649d0..a54660a221 100644 --- a/test/output/integerIntervalArea.html +++ b/test/output/integerIntervalArea.html @@ -70,28 +70,30 @@ ↑ y - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 x → diff --git a/test/output/lineInterval.svg b/test/output/lineInterval.svg new file mode 100644 index 0000000000..02554c8ff6 --- /dev/null +++ b/test/output/lineInterval.svg @@ -0,0 +1,127 @@ + + + + + 0 + 1 + 2 + 3 + 4 + 5 + + + + 2Jan + 4 + 6 + 8 + 10 + 12 + 14 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plots/index.ts b/test/plots/index.ts index 19bc952011..0d9fcaa806 100644 --- a/test/plots/index.ts +++ b/test/plots/index.ts @@ -11,8 +11,8 @@ import "./aapl-volume.js"; import "./anscombe-quartet.js"; import "./arc.js"; import "./armadillo.js"; -import "./arrow.js"; import "./arrow-dates.js"; +import "./arrow.js"; import "./aspectRatio.js"; import "./athletes-bins-colors.js"; import "./athletes-birthdays.js"; @@ -115,8 +115,8 @@ import "./google-trends-ridgeline.js"; import "./graticule.js"; import "./greek-gods.js"; import "./grid-choropleth.js"; -import "./grouped-rects.js"; import "./group-markers.js"; +import "./grouped-rects.js"; import "./hadcrut-warming-stripes.js"; import "./heatmap.js"; import "./hexbin-oranges.js"; @@ -154,6 +154,7 @@ import "./letter-frequency-lollipop.js"; import "./letter-frequency-wheel.js"; import "./libor-projections.js"; import "./likert-survey.js"; +import "./line-interval.js"; import "./linear-regression-cars.js"; import "./linear-regression-mtcars.js"; import "./linear-regression-penguins.js"; @@ -234,10 +235,10 @@ import "./population-by-latitude.js"; import "./population-by-longitude.js"; import "./projection-bleed-edges.js"; import "./projection-bleed-edges2.js"; -import "./projection-domain-ratio.js"; import "./projection-clip-angle-frame.js"; import "./projection-clip-angle.js"; import "./projection-clip-berghaus.js"; +import "./projection-domain-ratio.js"; import "./projection-fit-antarctica.js"; import "./projection-fit-bertin1953.js"; import "./projection-fit-conic.js"; diff --git a/test/plots/line-interval.ts b/test/plots/line-interval.ts new file mode 100644 index 0000000000..56b3f6efc7 --- /dev/null +++ b/test/plots/line-interval.ts @@ -0,0 +1,30 @@ +import * as Plot from "@observablehq/plot"; +import * as d3 from "d3"; +import {test} from "test/plot"; + +test(async function lineInterval() { + const random = d3.randomLcg(42); + const logins = ["Alice", "Bob", "Carol", "Dave", "Eve"]; + const dates = d3.utcDays(new Date("2024-01-01"), new Date("2024-01-15")); + const activity = dates.flatMap((date) => logins.filter(() => random() > 0.15).map((login) => ({date, login}))); + return Plot.plot({ + height: 200, + marks: [ + Plot.ruleY([0]), + Plot.areaY(activity, { + x: "date", + interval: "day", + fill: "login", + order: "-sum", + fillOpacity: 0.3, + y: 1, + curve: "catmull-rom" + }), + Plot.lineY( + activity, + Plot.stackY({x: "date", interval: "day", stroke: "login", order: "-sum", curve: "catmull-rom"}) + ), + Plot.dot(activity, Plot.stackY({x: "date", interval: "day", z: "login", fill: "login", order: "-sum"})) + ] + }); +});