Skip to content

Commit 81c3729

Browse files
committed
variable strokeDasharray and strokeDashoffset
for dasharray it would be ambiguous to accept an array… would it be a channel of dasharrays, or a constant dasharray? For this reason, only functions can create a variable channel.
1 parent de66b18 commit 81c3729

File tree

4 files changed

+141
-4
lines changed

4 files changed

+141
-4
lines changed

src/style.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ export function styles(
7575
const [vstroke, cstroke] = maybeColorChannel(stroke, defaultStroke);
7676
const [vstrokeOpacity, cstrokeOpacity] = maybeNumberChannel(strokeOpacity, defaultStrokeOpacity);
7777
const [vopacity, copacity] = maybeNumberChannel(opacity);
78+
const [vstrokeDasharray, cstrokeDasharray] = maybeDasharrayChannel(strokeDasharray);
79+
const [vstrokeDashoffset, cstrokeDashoffset] = maybeNumberChannel(strokeDashoffset);
7880

7981
// For styles that have no effect if there is no stroke, only apply the
8082
// defaults if the stroke is not the constant none. (If stroke is a channel,
@@ -110,8 +112,8 @@ export function styles(
110112
mark.strokeLinejoin = impliedString(strokeLinejoin, "miter");
111113
mark.strokeLinecap = impliedString(strokeLinecap, "butt");
112114
mark.strokeMiterlimit = impliedNumber(strokeMiterlimit, 4);
113-
mark.strokeDasharray = impliedString(strokeDasharray, "none");
114-
mark.strokeDashoffset = impliedString(strokeDashoffset, "0");
115+
mark.strokeDasharray = impliedString(cstrokeDasharray, "none");
116+
mark.strokeDashoffset = impliedString(cstrokeDashoffset, "0");
115117
}
116118

117119
mark.target = string(target);
@@ -130,6 +132,8 @@ export function styles(
130132
{name: "fill", value: vfill, scale: "color", optional: true},
131133
{name: "fillOpacity", value: vfillOpacity, scale: "opacity", optional: true},
132134
{name: "stroke", value: vstroke, scale: "color", optional: true},
135+
{name: "strokeDasharray", value: vstrokeDasharray, optional: true},
136+
{name: "strokeDashoffset", value: vstrokeDashoffset, optional: true},
133137
{name: "strokeOpacity", value: vstrokeOpacity, scale: "opacity", optional: true},
134138
{name: "strokeWidth", value: vstrokeWidth, optional: true},
135139
{name: "opacity", value: vopacity, scale: "opacity", optional: true}
@@ -154,25 +158,29 @@ export function applyTextGroup(selection, T) {
154158
if (T) selection.text(([i]) => formatDefault(T[i]));
155159
}
156160

157-
export function applyChannelStyles(selection, {target}, {ariaLabel: AL, title: T, fill: F, fillOpacity: FO, stroke: S, strokeOpacity: SO, strokeWidth: SW, opacity: O, href: H}) {
161+
export function applyChannelStyles(selection, {target}, {ariaLabel: AL, title: T, fill: F, fillOpacity: FO, stroke: S, strokeOpacity: SO, strokeWidth: SW, opacity: O, href: H, strokeDasharray: SDA, strokeDashoffset: SDO}) {
158162
if (AL) applyAttr(selection, "aria-label", i => AL[i]);
159163
if (F) applyAttr(selection, "fill", i => F[i]);
160164
if (FO) applyAttr(selection, "fill-opacity", i => FO[i]);
161165
if (S) applyAttr(selection, "stroke", i => S[i]);
162166
if (SO) applyAttr(selection, "stroke-opacity", i => SO[i]);
163167
if (SW) applyAttr(selection, "stroke-width", i => SW[i]);
168+
if (SDA) applyAttr(selection, "stroke-dasharray", i => SDA[i]);
169+
if (SDO) applyAttr(selection, "stroke-dashoffset", i => SDO[i]);
164170
if (O) applyAttr(selection, "opacity", i => O[i]);
165171
if (H) applyHref(selection, i => H[i], target);
166172
applyTitle(selection, T);
167173
}
168174

169-
export function applyGroupedChannelStyles(selection, {target}, {ariaLabel: AL, title: T, fill: F, fillOpacity: FO, stroke: S, strokeOpacity: SO, strokeWidth: SW, opacity: O, href: H}) {
175+
export function applyGroupedChannelStyles(selection, {target}, {ariaLabel: AL, title: T, fill: F, fillOpacity: FO, stroke: S, strokeOpacity: SO, strokeWidth: SW, opacity: O, href: H, strokeDasharray: SDA, strokeDashoffset: SDO}) {
170176
if (AL) applyAttr(selection, "aria-label", ([i]) => AL[i]);
171177
if (F) applyAttr(selection, "fill", ([i]) => F[i]);
172178
if (FO) applyAttr(selection, "fill-opacity", ([i]) => FO[i]);
173179
if (S) applyAttr(selection, "stroke", ([i]) => S[i]);
174180
if (SO) applyAttr(selection, "stroke-opacity", ([i]) => SO[i]);
175181
if (SW) applyAttr(selection, "stroke-width", ([i]) => SW[i]);
182+
if (SDA) applyAttr(selection, "stroke-dasharray", ([i]) => SDA[i]);
183+
if (SDO) applyAttr(selection, "stroke-dashoffset", ([i]) => SDO[i]);
176184
if (O) applyAttr(selection, "opacity", ([i]) => O[i]);
177185
if (H) applyHref(selection, ([i]) => H[i], target);
178186
applyTitleGroup(selection, T);
@@ -339,3 +347,7 @@ export function applyFrameAnchor({frameAnchor}, {width, height, marginTop, margi
339347
/^top/.test(frameAnchor) ? marginTop : /^bottom/.test(frameAnchor) ? height - marginBottom : (marginTop + height - marginBottom) / 2
340348
];
341349
}
350+
351+
function maybeDasharrayChannel(channel) {
352+
return typeof channel === "function" ? [channel] : [, channel];
353+
}
Lines changed: 96 additions & 0 deletions
Loading

test/plots/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ export {default as usPresidentialElection2020} from "./us-presidential-election-
201201
export {default as usPresidentialForecast2016} from "./us-presidential-forecast-2016.js";
202202
export {default as usRetailSales} from "./us-retail-sales.js";
203203
export {default as usStatePopulationChange} from "./us-state-population-change.js";
204+
export {default as variableStrokeDasharray} from "./variable-strokedasharray.js";
204205
export {default as vectorField} from "./vector-field.js";
205206
export {default as vectorFrame} from "./vector-frame.js";
206207
export {default as wealthBritainBar} from "./wealth-britain-bar.js";
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import * as Plot from "@observablehq/plot";
2+
3+
const data = Array.from(["none", "10 5", [20, 3], [30, 5, 10, 10], null],
4+
(strokeDasharray) => Array.from([0, 2, 20, 60, NaN],
5+
(strokeDashoffset) => ({strokeDasharray, strokeDashoffset})
6+
)
7+
).flat();
8+
9+
export default async function() {
10+
return Plot.plot({
11+
facet: {data, x: "strokeDasharray", y: "strokeDashoffset"},
12+
marks: [
13+
Plot.arrow(data, {
14+
x1: 0,
15+
x2: 1,
16+
y1: 0,
17+
y2: 1,
18+
strokeDasharray: d => d.strokeDasharray,
19+
strokeDashoffset: d => d.strokeDashoffset,
20+
bend: true,
21+
headLength: 0
22+
})
23+
],
24+
fx: {padding: 0.2},
25+
fy: {padding: 0.2},
26+
axis: null
27+
});
28+
}

0 commit comments

Comments
 (0)