Skip to content

Commit 2e5e279

Browse files
Filmbostock
andauthored
autoHeight factors in the auto and manual margins. (#1058)
* autoHeight factors in the auto and manual margins. See https://observablehq.com/@observablehq/plot-band-scale-bug-1045 fixes #1045 * Update src/dimensions.js Co-authored-by: Mike Bostock <mbostock@gmail.com> * remove addition * improve readability Co-authored-by: Mike Bostock <mbostock@gmail.com>
1 parent a033aa2 commit 2e5e279

File tree

5 files changed

+158
-130
lines changed

5 files changed

+158
-130
lines changed

src/dimensions.js

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,65 @@
1-
import {isProjection} from "./projection.js";
1+
import {hasProjection} from "./projection.js";
22
import {isOrdinalScale} from "./scales.js";
33
import {offset} from "./style.js";
44

5-
export function Dimensions(
6-
scales,
7-
geometry,
8-
{x: {axis: xAxis} = {}, y: {axis: yAxis} = {}, fx: {axis: fxAxis} = {}, fy: {axis: fyAxis} = {}},
9-
{
10-
projection,
11-
width = 640,
12-
height = autoHeight(scales, geometry || isProjection(projection)),
5+
export function Dimensions(scales, geometry, axes, options = {}) {
6+
// The default margins depend on the presence and orientation of axes. If the
7+
// corresponding scale is not present, the axis is necessarily null.
8+
const {x: {axis: x} = {}, y: {axis: y} = {}, fx: {axis: fx} = {}, fy: {axis: fy} = {}} = axes;
9+
10+
// Compute the default facet margins. When faceting is not present (and hence
11+
// the fx and fy axis are null), these will all be zero.
12+
let {
1313
facet: {
1414
margin: facetMargin,
15-
marginTop: facetMarginTop = facetMargin !== undefined ? facetMargin : fxAxis === "top" ? 30 : 0,
16-
marginRight: facetMarginRight = facetMargin !== undefined ? facetMargin : fyAxis === "right" ? 40 : 0,
17-
marginBottom: facetMarginBottom = facetMargin !== undefined ? facetMargin : fxAxis === "bottom" ? 30 : 0,
18-
marginLeft: facetMarginLeft = facetMargin !== undefined ? facetMargin : fyAxis === "left" ? 40 : 0
19-
} = {},
15+
marginTop: facetMarginTop = facetMargin !== undefined ? facetMargin : fx === "top" ? 30 : 0,
16+
marginRight: facetMarginRight = facetMargin !== undefined ? facetMargin : fy === "right" ? 40 : 0,
17+
marginBottom: facetMarginBottom = facetMargin !== undefined ? facetMargin : fx === "bottom" ? 30 : 0,
18+
marginLeft: facetMarginLeft = facetMargin !== undefined ? facetMargin : fy === "left" ? 40 : 0
19+
} = {}
20+
} = options;
21+
22+
// Coerce the facet margin options to numbers.
23+
facetMarginTop = +facetMarginTop;
24+
facetMarginRight = +facetMarginRight;
25+
facetMarginBottom = +facetMarginBottom;
26+
facetMarginLeft = +facetMarginLeft;
27+
28+
// Compute the default margins; while not always used, they may be needed to
29+
// compute the default height of the plot.
30+
const marginTopDefault = Math.max((x === "top" ? 30 : 0) + facetMarginTop, y || fy ? 20 : 0.5 - offset);
31+
const marginBottomDefault = Math.max((x === "bottom" ? 30 : 0) + facetMarginBottom, y || fy ? 20 : 0.5 + offset);
32+
const marginRightDefault = Math.max((y === "right" ? 40 : 0) + facetMarginRight, x || fx ? 20 : 0.5 + offset);
33+
const marginLeftDefault = Math.max((y === "left" ? 40 : 0) + facetMarginLeft, x || fx ? 20 : 0.5 - offset);
34+
35+
// Compute the actual margins. The order of precedence is: the side-specific
36+
// margin options, then the global margin option, then the defaults.
37+
let {
2038
margin,
21-
marginTop = margin !== undefined
22-
? margin
23-
: Math.max((xAxis === "top" ? 30 : 0) + facetMarginTop, yAxis || fyAxis ? 20 : 0.5 - offset),
24-
marginRight = margin !== undefined
25-
? margin
26-
: Math.max((yAxis === "right" ? 40 : 0) + facetMarginRight, xAxis || fxAxis ? 20 : 0.5 + offset),
27-
marginBottom = margin !== undefined
28-
? margin
29-
: Math.max((xAxis === "bottom" ? 30 : 0) + facetMarginBottom, yAxis || fyAxis ? 20 : 0.5 + offset),
30-
marginLeft = margin !== undefined
31-
? margin
32-
: Math.max((yAxis === "left" ? 40 : 0) + facetMarginLeft, xAxis || fxAxis ? 20 : 0.5 - offset)
33-
} = {}
34-
) {
39+
marginTop = margin !== undefined ? margin : marginTopDefault,
40+
marginRight = margin !== undefined ? margin : marginRightDefault,
41+
marginBottom = margin !== undefined ? margin : marginBottomDefault,
42+
marginLeft = margin !== undefined ? margin : marginLeftDefault
43+
} = options;
44+
45+
// Coerce the margin options to numbers.
46+
marginTop = +marginTop;
47+
marginRight = +marginRight;
48+
marginBottom = +marginBottom;
49+
marginLeft = +marginLeft;
50+
51+
// Compute the outer dimensions of the plot. If the top and bottom margins are
52+
// specified explicitly, adjust the automatic height accordingly.
53+
let {
54+
width = 640,
55+
height = autoHeight(scales, geometry || hasProjection(options)) +
56+
Math.max(0, marginTop - marginTopDefault + marginBottom - marginBottomDefault)
57+
} = options;
58+
59+
// Coerce the width and height.
60+
width = +width;
61+
height = +height;
62+
3563
return {
3664
width,
3765
height,

src/projection.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export function maybeProjection(projection, dimensions) {
2626
return projection?.({...dimensions, ...options});
2727
}
2828

29-
export function isProjection(projection) {
29+
export function hasProjection({projection} = {}) {
3030
if (projection == null) return false;
3131
if (typeof projection.stream === "function") return true; // d3 projection
3232
if (isObject(projection)) ({type: projection} = projection);

test/output/downloadsOrdinal.svg

Lines changed: 67 additions & 67 deletions
Loading

0 commit comments

Comments
 (0)