Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

polylinear (aka piecewise linear) scales with an unspecified range #530

Closed
wants to merge 12 commits into from
12 changes: 10 additions & 2 deletions src/scales.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ function autoScaleRangeX(scale, dimensions) {
if (scale.range === undefined) {
const {inset = 0} = scale;
const {width, marginLeft = 0, marginRight = 0} = dimensions;
scale.scale.range([marginLeft + inset, width - marginRight - inset]);
scale.scale.range(maybePiecewiseRange(marginLeft + inset, width - marginRight - inset, scale));
}
autoScaleRound(scale);
}
Expand All @@ -44,7 +44,7 @@ function autoScaleRangeY(scale, dimensions) {
if (scale.range === undefined) {
const {inset = 0} = scale;
const {height, marginTop = 0, marginBottom = 0} = dimensions;
const range = [height - marginBottom - inset, marginTop + inset];
const range = maybePiecewiseRange(height - marginBottom - inset, marginTop + inset, scale);
if (scale.type === "ordinal") range.reverse();
scale.scale.range(range);
}
Expand All @@ -57,6 +57,14 @@ function autoScaleRound(scale) {
}
}

function maybePiecewiseRange(start, end, {type, scale}) {
if (type === "quantitative") {
const l = scale.domain().length;
if (l > 2) return Array.from({length: l}, (_, i) => start + i / (l - 1) * (end - start));
}
return [start, end];
}

function Scale(key, channels = [], options = {}) {
switch (inferScaleType(key, channels, options)) {
case "diverging": return ScaleDiverging(key, channels, options);
Expand Down
116 changes: 116 additions & 0 deletions test/output/polylinear.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions test/plots/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export {default as penguinSpeciesGroup} from "./penguin-species-group.js";
export {default as penguinSpeciesIsland} from "./penguin-species-island.js";
export {default as penguinSpeciesIslandRelative} from "./penguin-species-island-relative.js";
export {default as penguinSpeciesIslandSex} from "./penguin-species-island-sex.js";
export {default as polylinear} from "./polylinear.js";
export {default as policeDeaths} from "./police-deaths.js";
export {default as policeDeathsBar} from "./police-deaths-bar.js";
export {default as randomBins} from "./random-bins.js";
Expand Down
45 changes: 45 additions & 0 deletions test/plots/polylinear.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import * as Plot from "@observablehq/plot";
import * as d3 from "d3";

const times = [
new Date(2013, 3, 5),
new Date(2013, 3, 11),
new Date(2013, 3, 14),
new Date(2013, 3, 16),
new Date(2013, 3, 18),
new Date(2013, 3, 21),
new Date(2013, 3, 27)
];

const events = [
{ date: new Date(2013, 3, 5, 13, 0), text: "Initiate" },
{ date: new Date(2013, 3, 11, 13, 0), text: "Begin" },
{ date: new Date(2013, 3, 13, 20, 0), text: "Entry" },
{ date: new Date(2013, 3, 15, 0, 0), text: "Test" },
{ date: new Date(2013, 3, 16, 0, 0), text: "Drive" },
{ date: new Date(2013, 3, 17, 8, 0), text: "Drive" },
{ date: new Date(2013, 3, 18, 15, 0), text: "Brake" },
{ date: new Date(2013, 3, 20, 10, 0), text: "Stop" },
{ date: new Date(2013, 3, 23, 14, 0), text: "Shutdown" }
Copy link
Member

@mbostock mbostock Sep 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are local times; could we use UTC to avoid being dependent on the local timezone? (And then use d3.utcDays instead of d3.timeDays etc. below.)

I’d also prefer if you changed your prettier settings to avoid the spaces inside the curly braces. 🙂

];

export default async function() {
return Plot.plot({
grid: true,
x: {
domain: times,
type: "linear",
ticks: [...d3.timeDays(...d3.extent(times)), times[times.length-1]],
tickFormat: d3.timeFormat("%d"),
inset: 20,
label: "date →"
},
color: { scheme: "cool" },
marks: [
Plot.barX(d3.pairs(times), {x1: "0", x2: "1", fill: (_,i) => i}),
Plot.dotX(events, {x: "date", fill: "white"}),
Plot.textX(events, {x: "date", text: "text", dx: -5, dy: -10, fill: "white", textAnchor: "start"})
],
height: 90
});
}