diff --git a/README.md b/README.md
index 85dd5f1190..6fb96f2eb3 100644
--- a/README.md
+++ b/README.md
@@ -1128,6 +1128,8 @@ The **fontSize** and **rotate** options can be specified as either channels or c
If the **frameAnchor** option is not specified, then **textAnchor** and **lineAnchor** default to middle. Otherwise, **textAnchor** defaults to start if **frameAnchor** is on the left, end if **frameAnchor** is on the right, and otherwise middle. Similarly, **lineAnchor** defaults to top if **frameAnchor** is on the top, bottom if **frameAnchor** is on the bottom, and otherwise middle.
+The **paintOrder** option defaults to “stroke” and the **strokeWidth** option defaults to 3. By setting **fill** to the foreground color and **stroke** to the background color (such as black and white, respectively), you can surround text with a “halo” which may improve legibility against a busy background.
+
#### Plot.text(*data*, *options*)
Returns a new text mark with the given *data* and *options*. If neither the **x** nor **y** nor **frameAnchor** options are specified, *data* is assumed to be an array of pairs [[*x₀*, *y₀*], [*x₁*, *y₁*], [*x₂*, *y₂*], …] such that **x** = [*x₀*, *x₁*, *x₂*, …] and **y** = [*y₀*, *y₁*, *y₂*, …].
diff --git a/src/marks/text.js b/src/marks/text.js
index a3cf632663..31a2041075 100644
--- a/src/marks/text.js
+++ b/src/marks/text.js
@@ -6,7 +6,9 @@ import {Mark} from "../plot.js";
import {applyChannelStyles, applyDirectStyles, applyIndirectStyles, applyAttr, applyTransform, offset, impliedString, applyFrameAnchor} from "../style.js";
const defaults = {
- strokeLinejoin: "round"
+ strokeLinejoin: "round",
+ strokeWidth: 3,
+ paintOrder: "stroke"
};
export class Text extends Mark {
diff --git a/src/style.js b/src/style.js
index a7acba1e8c..45b227b7ee 100644
--- a/src/style.js
+++ b/src/style.js
@@ -32,7 +32,8 @@ export function styles(
strokeWidth: defaultStrokeWidth,
strokeLinecap: defaultStrokeLinecap,
strokeLinejoin: defaultStrokeLinejoin,
- strokeMiterlimit: defaultStrokeMiterlimit
+ strokeMiterlimit: defaultStrokeMiterlimit,
+ paintOrder: defaultPaintOrder
}
) {
@@ -73,6 +74,10 @@ export function styles(
if (strokeLinecap === undefined) strokeLinecap = defaultStrokeLinecap;
if (strokeLinejoin === undefined) strokeLinejoin = defaultStrokeLinejoin;
if (strokeMiterlimit === undefined) strokeMiterlimit = defaultStrokeMiterlimit;
+
+ // The paint order only takes effect if there is both a fill and a stroke
+ // (at least if we ignore markers, which no built-in marks currently use).
+ if (cfill !== "none" && paintOrder === undefined) paintOrder = defaultPaintOrder;
}
const [vstrokeWidth, cstrokeWidth] = maybeNumberChannel(strokeWidth);
diff --git a/test/output/carsParcoords.svg b/test/output/carsParcoords.svg
index b17a3c4d79..ce58676303 100644
--- a/test/output/carsParcoords.svg
+++ b/test/output/carsParcoords.svg
@@ -450,6 +450,5 @@
- 101520253035404534567810015020025030035040045060801001201401601802002202,0002,5003,0003,5004,0004,5005,0008101214161820222470727476788082
- 101520253035404534567810015020025030035040045060801001201401601802002202,0002,5003,0003,5004,0004,5005,0008101214161820222470727476788082
+ 101520253035404534567810015020025030035040045060801001201401601802002202,0002,5003,0003,5004,0004,5005,0008101214161820222470727476788082
\ No newline at end of file
diff --git a/test/output/metroInequalityChange.svg b/test/output/metroInequalityChange.svg
index 3bfce31745..50ed22a347 100644
--- a/test/output/metroInequalityChange.svg
+++ b/test/output/metroInequalityChange.svg
@@ -334,5 +334,5 @@
- New YorkChicagoHoustonWashington, D.C.San FranciscoSan JoseFairfield, Conn.Binghamton, N.Y.
+ New YorkChicagoHoustonWashington, D.C.San FranciscoSan JoseFairfield, Conn.Binghamton, N.Y.
\ No newline at end of file
diff --git a/test/plots/cars-parcoords.js b/test/plots/cars-parcoords.js
index 1288efcc72..f18e87d53d 100644
--- a/test/plots/cars-parcoords.js
+++ b/test/plots/cars-parcoords.js
@@ -37,8 +37,7 @@ export default async function() {
marks: [
Plot.ruleY(dimensions),
Plot.line(data, {...xy, z: "name", stroke: "#444", strokeWidth: 0.5, strokeOpacity: 0.5}),
- Plot.text(ticks, {...xy, fill: null, stroke: "white", strokeWidth: 3, strokeLinejoin: "round", text: "value"}),
- Plot.text(ticks, {...xy, text: "value"})
+ Plot.text(ticks, {...xy, text: "value", fill: "black", stroke: "white"})
]
});
}
diff --git a/test/plots/metro-inequality-change.js b/test/plots/metro-inequality-change.js
index 00f49a135d..cef7bcfe61 100644
--- a/test/plots/metro-inequality-change.js
+++ b/test/plots/metro-inequality-change.js
@@ -32,6 +32,8 @@ export default async function() {
y: "R90_10_2015",
filter: "highlight",
text: "nyt_display",
+ fill: "currentColor",
+ stroke: "white",
dy: -8
})
]