Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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 @@ -1089,7 +1089,7 @@ The following channels are required:

* **text** - the text contents (a string, possibly with multiple lines)

If the **text** contains `\n`, `\r\n`, or `\r`, it will be rendered as multiple lines via tspan elements. If the **text** is specified as numbers or dates, a default formatter will automatically be applied, and the **fontVariant** will default to tabular-nums instead of normal. For more control over number and date formatting, consider [*number*.toLocaleString](https://observablehq.com/@mbostock/number-formatting), [*date*.toLocaleString](https://observablehq.com/@mbostock/date-formatting), [d3-format](https://github.com/d3/d3-format), or [d3-time-format](https://github.com/d3/d3-time-format). If **text** is not specified, it defaults to [0, 1, 2, …] so that something is visible by default.
If the **text** contains `\n`, `\r\n`, or `\r`, it will be rendered as multiple lines via tspan elements. If the **text** is specified as numbers or dates, a default formatter will automatically be applied, and the **fontVariant** will default to tabular-nums instead of normal. For more control over number and date formatting, consider [*number*.toLocaleString](https://observablehq.com/@mbostock/number-formatting), [*date*.toLocaleString](https://observablehq.com/@mbostock/date-formatting), [d3-format](https://github.com/d3/d3-format), or [d3-time-format](https://github.com/d3/d3-time-format). If **text** is not specified, it defaults to the identity function for primitive data (such as numbers, dates, and strings), and to the zero-based index [0, 1, 2, …] for objects (so that something identifying is visible by default).

In addition to the [standard mark options](#marks), the following optional channels are supported:

Expand Down
4 changes: 2 additions & 2 deletions src/marks/text.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {create, isoFormat, namespaces} from "d3";
import {nonempty} from "../defined.js";
import {formatNumber} from "../format.js";
import {indexOf, identity, string, maybeNumberChannel, maybeTuple, numberChannel, isNumeric, isTemporal, keyword, maybeFrameAnchor} from "../options.js";
import {indexOf, identity, string, maybeNumberChannel, maybeTuple, numberChannel, isNumeric, isTemporal, keyword, maybeFrameAnchor, isTextual} from "../options.js";
import {Mark} from "../plot.js";
import {applyChannelStyles, applyDirectStyles, applyIndirectStyles, applyAttr, applyTransform, offset, impliedString, applyFrameAnchor} from "../style.js";

Expand All @@ -14,7 +14,7 @@ export class Text extends Mark {
const {
x,
y,
text = indexOf,
text = data != null && isTextual(data) ? identity : indexOf,
textAnchor,
lineAnchor = "middle",
lineHeight = 1,
Expand Down
7 changes: 7 additions & 0 deletions src/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,13 @@ export function numberChannel(source) {
};
}

export function isTextual(values) {
for (const value of values) {
if (value == null) continue;
return typeof value !== "object" || value instanceof Date;
}
}

export function isOrdinal(values) {
for (const value of values) {
if (value == null) continue;
Expand Down
25 changes: 25 additions & 0 deletions test/marks/text-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,36 @@ it("text() has the expected defaults", () => {
assert.strictEqual(text.shapeRendering, undefined);
assert.strictEqual(text.textAnchor, undefined);
assert.strictEqual(text.lineAnchor, "middle");
assert.strictEqual(text.frameAnchor, "middle");
assert.strictEqual(text.dx, 0);
assert.strictEqual(text.dy, 0);
assert.strictEqual(text.rotate, 0);
});

it("text(strings, {frameAnchor}) has the expected defaults", () => {
const data = ["hello"];
const text = Plot.text(data, {frameAnchor: "middle"});
assert.strictEqual(text.data, data);
assert.strictEqual(text.transform, undefined);
assert.deepStrictEqual(text.channels.map(c => c.name), ["text"]);
assert.deepStrictEqual(text.channels.map(c => Plot.valueof(data, c.value)), [data]);
assert.strictEqual(text.textAnchor, undefined);
assert.strictEqual(text.lineAnchor, "middle");
assert.strictEqual(text.frameAnchor, "middle");
});

it("text(dates, {frameAnchor}) has the expected defaults", () => {
const data = [new Date("2021-01-01")];
const text = Plot.text(data, {frameAnchor: "middle"});
assert.strictEqual(text.data, data);
assert.strictEqual(text.transform, undefined);
assert.deepStrictEqual(text.channels.map(c => c.name), ["text"]);
assert.deepStrictEqual(text.channels.map(c => Plot.valueof(data, c.value)), [data]);
assert.strictEqual(text.textAnchor, undefined);
assert.strictEqual(text.lineAnchor, "middle");
assert.strictEqual(text.frameAnchor, "middle");
});

it("text(data, {title}) specifies an optional title channel", () => {
const text = Plot.text(undefined, {title: "x"});
const title = text.channels.find(c => c.name === "title");
Expand Down