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

document axis #1403

Merged
merged 11 commits into from
Apr 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1091,7 +1091,7 @@ The axis mark’s default margins depend on its orientation (**anchor**) as foll
* *bottom* - 0, 20, 30, 20
* *left* - 20, 0, 20, 40

For simplicity’s sake and for consistent layout across plots, axis margins are not automatically sized to make room for tick labels; instead, shorten your tick labels (for example using the *k* SI-prefix tick format, or setting a *scale*.transform to show thousands or millions, or setting the **lineWidth** option to wrap long labels) or increase the margins as needed.
For simplicity’s sake and for consistent layout across plots, axis margins are not automatically sized to make room for tick labels; instead, shorten your tick labels (for example using the *k* SI-prefix tick format, or setting a *scale*.transform to show thousands or millions, or setting the **textOverflow** option to *ellipsis* and the **lineWidth** option to clip long labels) or increase the margins as needed.

#### Plot.axisX(*data*, *options*)

Expand Down
223 changes: 181 additions & 42 deletions src/marks/axis.d.ts
Original file line number Diff line number Diff line change
@@ -1,70 +1,209 @@
import type {CompoundMark, Data, MarkOptions, RenderableMark} from "../mark.js";
import type {CompoundMark, Data, MarkOptions} from "../mark.js";
import type {ScaleOptions} from "../scales.js";
import type {RuleXOptions, RuleYOptions} from "./rule.js";
import type {RuleX, RuleXOptions, RuleY, RuleYOptions} from "./rule.js";
import type {TextOptions} from "./text.js";
import type {TickXOptions, TickYOptions} from "./tick.js";

export type AxisAnchor = "top" | "right" | "bottom" | "left";

interface GridOptions {
anchor?: AxisAnchor;
interval?: ScaleOptions["interval"];
ticks?: ScaleOptions["ticks"];
tickSpacing?: ScaleOptions["tickSpacing"];
/** The subset of scale options for grids. */
type GridScaleOptions = Pick<ScaleOptions, "interval" | "ticks" | "tickSpacing">;

/** The subset of scale options for axes. */
type AxisScaleOptions = Pick<ScaleOptions, "tickSize" | "tickPadding" | "tickFormat" | "tickRotate" | "label" | "labelOffset" | "labelAnchor">; // prettier-ignore

/** Options for the grid marks. */
export interface GridOptions extends GridScaleOptions {
/**
* The side of the frame on which to place the axis: *top* or *bottom* for
* horizontal axes (axisX and axisFx) and their associated vertical grids
* (gridX and gridFx), or *left* or *right* for vertical axes (axisY and
* axisFY) and their associated horizontal grids (gridY and gridFy).
*
* The default **anchor** depends on the associated scale:
*
* - *x* - *bottom*
* - *y* - *left*
* - *fx* - *top* if there is a *bottom* *x* axis, and otherwise *bottom*
* - *fy* - *right* if there is a *left* *y* axis, and otherwise *right*
*
* For grids, the **anchor** also affects the extent of grid lines when the
* opposite dimension is specified (**x** for gridY and **y** for gridX). For
* example, to draw a horizontal gridY between the *right* edge of the frame
* and the specified **x** value:
*
* ```js
* Plot.gridY({x: (y) => aapl.find((d) => d.Close >= y)?.Date, anchor: "right"})
* ```
*/
anchor?: "top" | "right" | "bottom" | "left";

/**
* A shorthand for setting both **fill** and **stroke**; affects the stroke of
* tick vectors and grid rules, and the fill of tick texts and axis label
* texts; defaults to *currentColor*.
*/
color?: MarkOptions["stroke"];

/**
* A shorthand for setting both **fillOpacity** and **strokeOpacity**; affects
* the stroke opacity of tick vectors and grid rules, and the fill opacity of
* tick texts and axis label texts; defaults to 1 for axes and 0.1 for grids.
*/
opacity?: MarkOptions["opacity"];
}

interface AxisOptions extends GridOptions, MarkOptions, TextOptions {
tickSize?: ScaleOptions["tickSize"];
tickPadding?: ScaleOptions["tickPadding"];
tickFormat?: ScaleOptions["tickFormat"];
tickRotate?: ScaleOptions["tickRotate"];
grid?: ScaleOptions["grid"];
line?: ScaleOptions["line"];
label?: ScaleOptions["label"];
labelOffset?: ScaleOptions["labelOffset"];
labelAnchor?: ScaleOptions["labelAnchor"];
/** Options for the axis marks. */
export interface AxisOptions extends GridOptions, MarkOptions, TextOptions, AxisScaleOptions {
/** The tick text **stroke**, say for a *white* outline to improve legibility; defaults to null. */
textStroke?: MarkOptions["stroke"];
/** The tick text **strokeOpacity**; defaults to 1; has no effect unless **textStroke** is set. */
textStrokeOpacity?: MarkOptions["strokeOpacity"];
/** The tick text **strokeWidth**; defaults to 4; has no effect unless **textStroke** is set. */
textStrokeWidth?: MarkOptions["strokeWidth"];
}

/** Options for the axisX and axisFx marks. */
export interface AxisXOptions extends AxisOptions, TickXOptions {}

/** Options for the axisY and axisFy marks. */
export interface AxisYOptions extends AxisOptions, TickYOptions {}

/** Options for the gridX and gridFx marks. */
export interface GridXOptions extends GridOptions, Omit<RuleXOptions, "interval"> {}

/** Options for the gridY and gridFy marks. */
export interface GridYOptions extends GridOptions, Omit<RuleYOptions, "interval"> {}

export function axisY(options?: AxisYOptions): CompoundMark;

/**
* Returns a new compound axis mark to document the visual encoding of the
* vertical position *y* scale, comprised of (up to) three marks: a vector for
* ticks, a text for tick labels, and another text for an axis label. The *data*
* defaults to tick values sampled from the *y* scale’s domain; if desired,
* specify the axis mark’s *data* explicitly, or use one of the **ticks**,
* **tickSpacing**, or **interval** options.
*
* The **facetAnchor** option defaults to *right-empty* if **anchor** is
* *right*, and *left-empty* if **anchor** is *left*. The default margins
* likewise depend on **anchor** as follows; in order of **marginTop**,
* **marginRight**, **marginBottom**, and **marginLeft**, in pixels:
*
* - *right* - 20, 40, 20, 0
* - *left* - 20, 0, 20, 40
*
* For simplicity, and for consistent layout across plots, default axis margins
* are not affected by tick labels. If tick labels are too long, either increase
* the margin or shorten the labels: use the *k* SI-prefix tick format; use the
* **transform** *y*-scale option to show thousands or millions; or use the
* **textOverflow** and **lineWidth** options to clip.
*/
export function axisY(data?: Data, options?: AxisYOptions): CompoundMark;
export function axisY(options?: AxisYOptions): CompoundMark;

export function axisFy(options?: AxisYOptions): CompoundMark;

/**
* Returns a new compound axis mark to document the visual encoding of the
* vertical facet position *fy* scale, comprised of (up to) three marks: a
* vector for ticks, a text for tick labels, and another text for an axis label.
* The *data* defaults to the *fy* scale’s domain; if desired, specify the axis
* mark’s *data* explicitly, or use one of the **ticks**, **tickSpacing**, or
* **interval** options.
*
* The **facetAnchor** option defaults to *right-empty* if **anchor** is
* *right*, and *left-empty* if **anchor** is *left*. The default margins
* likewise depend on **anchor** as follows; in order of **marginTop**,
* **marginRight**, **marginBottom**, and **marginLeft**, in pixels:
*
* - *right* - 20, 40, 20, 0
* - *left* - 20, 0, 20, 40
*
* For simplicity, and for consistent layout across plots, default axis margins
* are not affected by tick labels. If tick labels are too long, either increase
* the margin or shorten the labels, say by using the **textOverflow** and
* **lineWidth** options to clip.
*/
export function axisFy(data?: Data, options?: AxisYOptions): CompoundMark;
export function axisFy(options?: AxisYOptions): CompoundMark;

export function axisX(options?: AxisXOptions): CompoundMark;

/**
* Returns a new compound axis mark to document the visual encoding of the
* horizontal position *x* scale, comprised of (up to) three marks: a vector for
* ticks, a text for tick labels, and another text for an axis label. The *data*
* defaults to tick values sampled from the *x* scale’s domain; if desired,
* specify the axis mark’s *data* explicitly, or use one of the **ticks**,
* **tickSpacing**, or **interval** options.
*
* The **facetAnchor** option defaults to *bottom-empty* if **anchor** is
* *bottom*, and *top-empty* if **anchor** is *top*. The default margins
* likewise depend on **anchor** as follows; in order of **marginTop**,
* **marginRight**, **marginBottom**, and **marginLeft**, in pixels:
*
* - *top* - 30, 20, 0, 20
* - *bottom* - 0, 20, 30, 20
*
* For simplicity, and for consistent layout across plots, default axis margins
* are not affected by tick labels. If tick labels are too long, either increase
* the margin or shorten the labels: use the *k* SI-prefix tick format; use the
* **transform** *x*-scale option to show thousands or millions; or use the
* **textOverflow** and **lineWidth** options to clip; or use the **tickRotate**
* option to rotate.
*/
export function axisX(data?: Data, options?: AxisXOptions): CompoundMark;
export function axisX(options?: AxisXOptions): CompoundMark;

export function axisFx(options?: AxisXOptions): CompoundMark;

/**
* Returns a new compound axis mark to document the visual encoding of the
* horizontal facet position *fx* scale, comprised of (up to) three marks: a
* vector for ticks, a text for tick labels, and another text for an axis label.
* The *data* defaults to the *fx* scale’s domain; if desired, specify the axis
* mark’s *data* explicitly, or use one of the **ticks**, **tickSpacing**, or
* **interval** options.
*
* The **facetAnchor** and **frameAnchor** options defaults to **anchor**. The
* default margins likewise depend on **anchor** as follows; in order of
* **marginTop**, **marginRight**, **marginBottom**, and **marginLeft**, in
* pixels:
*
* - *top* - 30, 20, 0, 20
* - *bottom* - 0, 20, 30, 20
*
* For simplicity, and for consistent layout across plots, default axis margins
* are not affected by tick labels. If tick labels are too long, either increase
* the margin or shorten the labels, say by using the **textOverflow** and
* **lineWidth** options to clip, or using the **tickRotate** option to rotate.
*/
export function axisFx(data?: Data, options?: AxisXOptions): CompoundMark;
export function axisFx(options?: AxisXOptions): CompoundMark;

export function gridY(options?: GridYOptions): RenderableMark;

export function gridY(data?: Data, options?: GridYOptions): RenderableMark;

export function gridFy(options?: GridYOptions): RenderableMark;

export function gridFy(data?: Data, options?: GridYOptions): RenderableMark;

export function gridX(options?: GridXOptions): RenderableMark;

export function gridX(data?: Data, options?: GridXOptions): RenderableMark;

export function gridFx(options?: GridXOptions): RenderableMark;

export function gridFx(data?: Data, options?: GridXOptions): RenderableMark;
/**
* Returns a new horizontally-positioned ruleX mark (a vertical line, |) that
* renders a grid for the *x* scale. The *data* defaults to tick values sampled
* from the *x* scale’s domain; if desired, specify the *data* explicitly, or
* use one of the **ticks**, **tickSpacing**, or **interval** options.
*/
export function gridX(data?: Data, options?: GridXOptions): RuleX;
export function gridX(options?: GridXOptions): RuleX;

/**
* Returns a new horizontally-positioned ruleX mark (a vertical line, |) that
* renders a grid for the *fx* scale. The *data* defaults to the *fx* scale’s
* domain; if desired, specify the *data* explicitly, or use the **ticks**
* option.
*/
export function gridFx(data?: Data, options?: GridXOptions): RuleX;
export function gridFx(options?: GridXOptions): RuleX;

/**
* Returns a new vertically-positioned ruleY mark (a horizontal line, —) that
* renders a grid for the *y* scale. The *data* defaults to tick values sampled
* from the *y* scale’s domain; if desired, specify the *data* explicitly, or
* use one of the **ticks**, **tickSpacing**, or **interval** options.
*/
export function gridY(data?: Data, options?: GridYOptions): RuleY;
export function gridY(options?: GridYOptions): RuleY;

/**
* Returns a new vertically-positioned ruleY mark (a horizontal line, —) that
* renders a grid for the *fy* scale. The *data* defaults to the *fy* scale’s
* domain; if desired, specify the *data* explicitly, or use the **ticks**
* option.
*/
export function gridFy(data?: Data, options?: GridYOptions): RuleY;
export function gridFy(options?: GridYOptions): RuleY;
38 changes: 28 additions & 10 deletions src/scales.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type {InsetOptions} from "./inset.js";
import type {NiceInterval, RangeInterval} from "./interval.js";
import type {LegendOptions} from "./legends.js";
import type {AxisAnchor} from "./marks/axis.js";
import type {AxisOptions} from "./marks/axis.js";

/**
* How to interpolate range (output) values for continuous scales; one of:
Expand Down Expand Up @@ -294,12 +294,22 @@ export interface ScaleDefaults extends InsetOptions {
padding?: number;

/**
* Where to place the implicit axis; equivalent to the **anchor** option of
* the axis mark.
* The side of the frame on which to place the implicit axis: *top* or
* *bottom* for *x* or *fx*, or *left* or *right* for *y* or *fy*. The default
* depends on the scale:
*
* For position scales only.
* - *x* - *bottom*
* - *y* - *left*
* - *fx* - *top* if there is a *bottom* *x* axis, and otherwise *bottom*
* - *fy* - *right* if there is a *left* *y* axis, and otherwise *right*
*
* If *both*, an implicit axis will be rendered on both sides of the plot
* (*top* and *bottom* for *x* or *fx*, or *left* and *right* for *y* or
* *fy*). If null, the implicit axis is suppressed.
*
* For position axes only.
*/
axis?: AxisAnchor | "both" | boolean | null;
axis?: AxisOptions["anchor"] | "both" | boolean | null;

/**
* Whether to show a grid aligned with the scale’s ticks. If true, show a grid
Expand All @@ -313,7 +323,8 @@ export interface ScaleDefaults extends InsetOptions {

/**
* A textual label to show on the axis or legend; if null, show no label. By
* default the scale label is inferred from channel definitions.
* default the scale label is inferred from channel definitions, possibly with
* an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.
*
* For axes and legends only.
*/
Expand Down Expand Up @@ -533,7 +544,8 @@ export interface ScaleOptions extends ScaleDefaults {

/**
* The length of axis tick marks in pixels; negative values extend in the
* opposite direction.
* opposite direction. Defaults to 6 for *x* and *y* axes and *color* and
* *opacity* *ramp* legends, and 0 for *fx* and *fy* axes.
*
* For axes and legends.
*/
Expand All @@ -550,7 +562,8 @@ export interface ScaleOptions extends ScaleDefaults {

/**
* The distance between an axis tick mark and its associated text label (in
* pixels); defaults to 3.
* pixels); often defaults to 3, but may be affected by **tickSize** and
* **tickRotate**.
*/
tickPadding?: number;

Expand Down Expand Up @@ -585,8 +598,13 @@ export interface ScaleOptions extends ScaleDefaults {
ariaDescription?: string;

/**
* Where to place the axis **label**; either *center* or one of the frame
* sides: *top*, *right*, *bottom*, *left*.
* Where to place the axis **label** relative to the plot’s frame. For
* vertical position scales (*y* and *fy*), may be *top*, *bottom*, or
* *center*; for horizontal position scales (*x* and *fx*), may be *left*,
* *right*, or *center*. Defaults to *center* for ordinal scales (including
* *fx* and *fy*), and otherwise *top* for *y*, and *right* for *x*.
*
* For position axes only.
*/
labelAnchor?: "top" | "right" | "bottom" | "left" | "center";

Expand Down