Skip to content

Commit daee8b2

Browse files
authored
replace axis line with frame anchor (#1241)
* replace axis line with frame anchor * remove explicit axis line option
1 parent 1da65ff commit daee8b2

File tree

6 files changed

+61
-65
lines changed

6 files changed

+61
-65
lines changed

src/marks/axis.js

Lines changed: 3 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import {extent, format, utcFormat} from "d3";
2-
import {create} from "../context.js";
32
import {formatDefault} from "../format.js";
4-
import {Mark, marks} from "../mark.js";
3+
import {marks} from "../mark.js";
54
import {radians} from "../math.js";
65
import {range, valueof, arrayify, constant, keyword, identity, number} from "../options.js";
7-
import {isNone, isNoneish, isIterable, isTemporal, maybeInterval, orderof} from "../options.js";
6+
import {isNoneish, isIterable, isTemporal, maybeInterval, orderof} from "../options.js";
87
import {isTemporalScale} from "../scales.js";
9-
import {applyDirectStyles, applyIndirectStyles, applyTransform, offset} from "../style.js";
8+
import {offset} from "../style.js";
109
import {initializer} from "../transforms/basic.js";
1110
import {ruleX, ruleY} from "./rule.js";
1211
import {text, textX, textY} from "./text.js";
@@ -64,7 +63,6 @@ function axisKy(
6463
anchor,
6564
data,
6665
{
67-
line,
6866
color = "currentColor",
6967
opacity = 1,
7068
stroke = color,
@@ -95,14 +93,6 @@ function axisKy(
9593
tickRotate = number(tickRotate);
9694
if (labelAnchor !== undefined) labelAnchor = keyword(labelAnchor, "labelAnchor", ["center", "top", "bottom"]);
9795
return marks(
98-
k === "y" && line && !isNone(line)
99-
? new AxisLine(k, anchor, {
100-
stroke: line === true ? stroke : line,
101-
strokeOpacity,
102-
strokeWidth,
103-
...options
104-
})
105-
: null,
10696
tickSize && !isNoneish(stroke)
10797
? axisTickKy(k, anchor, data, {
10898
stroke,
@@ -180,7 +170,6 @@ function axisKx(
180170
anchor,
181171
data,
182172
{
183-
line,
184173
color = "currentColor",
185174
opacity = 1,
186175
stroke = color,
@@ -211,14 +200,6 @@ function axisKx(
211200
tickRotate = number(tickRotate);
212201
if (labelAnchor !== undefined) labelAnchor = keyword(labelAnchor, "labelAnchor", ["center", "left", "right"]);
213202
return marks(
214-
k === "x" && line && !isNone(line)
215-
? new AxisLine(k, anchor, {
216-
stroke: line === true ? stroke : line,
217-
strokeOpacity,
218-
strokeWidth,
219-
...options
220-
})
221-
: null,
222203
tickSize && !isNoneish(stroke)
223204
? axisTickKx(k, anchor, data, {
224205
stroke,
@@ -572,34 +553,6 @@ function axisMark(mark, k, ariaLabel, data, options, initialize) {
572553
return m;
573554
}
574555

575-
const axisLineDefaults = {
576-
fill: null,
577-
stroke: "currentColor"
578-
};
579-
580-
class AxisLine extends Mark {
581-
constructor(k, anchor, {facetAnchor = anchor + "-empty", ...options} = {}) {
582-
super(undefined, undefined, {facetAnchor, ...options}, axisLineDefaults);
583-
this.anchor = anchor;
584-
this.ariaLabel = `${k}-axis line`;
585-
}
586-
render(index, scales, channels, dimensions, context) {
587-
const {marginTop, marginRight, marginBottom, marginLeft, width, height} = dimensions;
588-
const {anchor} = this;
589-
const tx = anchor === "left" ? -0.5 : anchor === "right" ? 0.5 : undefined;
590-
const ty = anchor === "top" ? -0.5 : anchor === "bottom" ? 0.5 : undefined;
591-
return create("svg:line", context)
592-
.call(applyIndirectStyles, this, dimensions, context)
593-
.call(applyDirectStyles, this)
594-
.call(applyTransform, this, {}, tx, ty)
595-
.attr("x1", anchor === "right" ? width - marginRight : marginLeft)
596-
.attr("y1", anchor === "bottom" ? height - marginBottom : marginTop)
597-
.attr("x2", anchor === "left" ? marginLeft : width - marginRight)
598-
.attr("y2", anchor === "top" ? marginTop : height - marginBottom)
599-
.node();
600-
}
601-
}
602-
603556
function inferTextChannel(scale, ticks, tickFormat) {
604557
return {value: inferTickFormat(scale, ticks, tickFormat)};
605558
}

src/marks/frame.js

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {create} from "../context.js";
22
import {Mark} from "../mark.js";
3-
import {number} from "../options.js";
3+
import {maybeKeyword, number} from "../options.js";
44
import {applyDirectStyles, applyIndirectStyles, applyTransform} from "../style.js";
55

66
const defaults = {
@@ -9,10 +9,27 @@ const defaults = {
99
stroke: "currentColor"
1010
};
1111

12+
const lineDefaults = {
13+
ariaLabel: "frame",
14+
fill: null,
15+
stroke: "currentColor",
16+
strokeLinecap: "square"
17+
};
18+
1219
export class Frame extends Mark {
1320
constructor(options = {}) {
14-
const {inset = 0, insetTop = inset, insetRight = inset, insetBottom = inset, insetLeft = inset, rx, ry} = options;
15-
super(undefined, undefined, options, defaults);
21+
const {
22+
anchor = null,
23+
inset = 0,
24+
insetTop = inset,
25+
insetRight = inset,
26+
insetBottom = inset,
27+
insetLeft = inset,
28+
rx,
29+
ry
30+
} = options;
31+
super(undefined, undefined, options, anchor == null ? defaults : lineDefaults);
32+
this.anchor = maybeKeyword(anchor, "anchor", ["top", "right", "bottom", "left"]);
1633
this.insetTop = number(insetTop);
1734
this.insetRight = number(insetRight);
1835
this.insetBottom = number(insetBottom);
@@ -22,17 +39,33 @@ export class Frame extends Mark {
2239
}
2340
render(index, scales, channels, dimensions, context) {
2441
const {marginTop, marginRight, marginBottom, marginLeft, width, height} = dimensions;
25-
const {insetTop, insetRight, insetBottom, insetLeft, rx, ry} = this;
26-
return create("svg:rect", context)
42+
const {anchor, insetTop, insetRight, insetBottom, insetLeft, rx, ry} = this;
43+
const x1 = marginLeft + insetLeft;
44+
const x2 = width - marginRight - insetRight;
45+
const y1 = marginTop + insetTop;
46+
const y2 = height - marginBottom - insetBottom;
47+
return create(anchor ? "svg:line" : "svg:rect", context)
2748
.call(applyIndirectStyles, this, dimensions, context)
2849
.call(applyDirectStyles, this)
2950
.call(applyTransform, this, {})
30-
.attr("x", marginLeft + insetLeft)
31-
.attr("y", marginTop + insetTop)
32-
.attr("width", width - marginLeft - marginRight - insetLeft - insetRight)
33-
.attr("height", height - marginTop - marginBottom - insetTop - insetBottom)
34-
.attr("rx", rx)
35-
.attr("ry", ry)
51+
.call(
52+
anchor === "left"
53+
? (line) => line.attr("x1", x1).attr("x2", x1).attr("y1", y1).attr("y2", y2)
54+
: anchor === "right"
55+
? (line) => line.attr("x1", x2).attr("x2", x2).attr("y1", y1).attr("y2", y2)
56+
: anchor === "top"
57+
? (line) => line.attr("x1", x1).attr("x2", x2).attr("y1", y1).attr("y2", y1)
58+
: anchor === "bottom"
59+
? (line) => line.attr("x1", x1).attr("x2", x2).attr("y1", y2).attr("y2", y2)
60+
: (rect) =>
61+
rect
62+
.attr("x", x1)
63+
.attr("y", y1)
64+
.attr("width", x2 - x1)
65+
.attr("height", y2 - y1)
66+
.attr("rx", rx)
67+
.attr("ry", ry)
68+
)
3669
.node();
3770
}
3871
}

src/plot.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {Facets, facetExclude, facetGroups, facetOrder, facetTranslate, facetFilt
66
import {Legends, exposeLegends} from "./legends.js";
77
import {Mark} from "./mark.js";
88
import {axisFx, axisFy, axisX, axisY, gridFx, gridFy, gridX, gridY} from "./marks/axis.js";
9+
import {frame} from "./marks/frame.js";
910
import {arrayify, isColor, isIterable, isNone, isScaleOptions, map, yes, maybeInterval} from "./options.js";
1011
import {Scales, ScaleFunctions, autoScaleRange, exposeScales, innerDimensions, outerDimensions} from "./scales.js";
1112
import {position, registry as scaleRegistry} from "./scales/index.js";
@@ -513,6 +514,8 @@ function maybeAxis(axes, axis, axisType, primary, secondary, defaults, options)
513514
if (!axis) return;
514515
const both = isBoth(axis);
515516
options = axisOptions(both ? primary : axis, defaults, options);
517+
const {line} = options;
518+
if ((axisType === axisY || axisType === axisX) && line && !isNone(line)) axes.push(frame(lineOptions(options)));
516519
axes.push(axisType(options));
517520
if (both) axes.push(axisType({...options, anchor: secondary, label: null}));
518521
}
@@ -563,6 +566,11 @@ function axisOptions(
563566
};
564567
}
565568

569+
function lineOptions(options) {
570+
const {anchor, line} = options;
571+
return {anchor, facetAnchor: anchor + "-empty", stroke: line === true ? undefined : line};
572+
}
573+
566574
function gridOptions(
567575
grid,
568576
{

test/output/athletesSportWeight.svg

Lines changed: 1 addition & 1 deletion
Loading

test/output/carsDodge.svg

Lines changed: 1 addition & 1 deletion
Loading

test/plots/athletes-sport-weight.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ export default async function () {
66
return Plot.plot({
77
marginLeft: 100,
88
grid: true,
9-
x: {line: true},
109
color: {scheme: "YlGnBu", zero: true},
11-
marks: [Plot.barX(athletes, Plot.binX({fill: "proportion-facet"}, {x: "weight", fy: "sport", thresholds: 60}))]
10+
marks: [
11+
Plot.barX(athletes, Plot.binX({fill: "proportion-facet"}, {x: "weight", fy: "sport", thresholds: 60})),
12+
Plot.frame({anchor: "bottom", facetAnchor: "bottom"})
13+
]
1214
});
1315
}

0 commit comments

Comments
 (0)