Skip to content

Commit 2071c97

Browse files
authored
Axis alignment over multiple panels (#5826)
* Don't fix viewport size * add null padding * Fix viewport size, but flexibly * add test * add news bullet
1 parent 1a6e495 commit 2071c97

File tree

4 files changed

+189
-1
lines changed

4 files changed

+189
-1
lines changed

NEWS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# ggplot2 (development version)
22

3+
* Axis labels are now justified across facet panels (@teunbrand, #5820)
34
* Fixed bug in `stat_function()` so x-axis title now produced automatically
45
when no data added. (@phispu, #5647).
56
* geom_sf now accepts shape names (@sierrajohnson, #5808)

R/guide-axis.R

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ GuideAxis <- ggproto(
424424
# Unlist the 'label' grobs
425425
z <- if (params$position == "left") c(2, 1, 3) else 1:3
426426
z <- rep(z, c(1, length(grobs$labels), 1))
427+
has_labels <- !is.zero(grobs$labels[[1]])
427428
grobs <- c(list(grobs$ticks), grobs$labels, list(grobs$title))
428429

429430
# Initialise empty gtable
@@ -445,10 +446,25 @@ GuideAxis <- ggproto(
445446
vp <- exec(
446447
viewport,
447448
!!params$orth_aes := unit(params$orth_side, "npc"),
448-
!!params$orth_size := params$measure_gtable(gt),
449+
!!params$orth_size := max(params$measure_gtable(gt), unit(1, "npc")),
449450
just = params$opposite
450451
)
451452

453+
# Add null-unit padding to justify based on eventual gtable cell shape
454+
# rather than dimensions of this axis alone.
455+
if (has_labels && params$position %in% c("left", "right")) {
456+
where <- layout$l[-c(1, length(layout$l))]
457+
just <- with(elements$text, rotate_just(angle, hjust, vjust))$hjust %||% 0.5
458+
gt <- gtable_add_cols(gt, unit(just, "null"), pos = min(where) - 1)
459+
gt <- gtable_add_cols(gt, unit(1 - just, "null"), pos = max(where) + 1)
460+
}
461+
if (has_labels && params$position %in% c("top", "bottom")) {
462+
where <- layout$t[-c(1, length(layout$t))]
463+
just <- with(elements$text, rotate_just(angle, hjust, vjust))$vjust %||% 0.5
464+
gt <- gtable_add_rows(gt, unit(1 - just, "null"), pos = min(where) - 1)
465+
gt <- gtable_add_rows(gt, unit(just, "null"), pos = max(where) + 1)
466+
}
467+
452468
# Assemble with axis line
453469
absoluteGrob(
454470
gList(axis_line, gt),
Lines changed: 144 additions & 0 deletions
Loading

tests/testthat/test-facet-labels.R

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,30 @@ test_that("parsed labels are rendered correctly", {
157157
facet_wrap(~ f, labeller = label_parsed)
158158
)
159159
})
160+
161+
test_that("outside-justified labels are justified across panels", {
162+
163+
df <- data.frame(
164+
x = c("X\nX\nX\nX\nX", "X"),
165+
y = c("YYYYY", "Y"),
166+
f1 = c("A", "B"),
167+
f2 = c("C", "D")
168+
)
169+
170+
# By default, axis labels are inside-justified so it doesn't matter whether
171+
# justification occurs across panels. This changes for outside-justification.
172+
# See #5820
173+
174+
p <- ggplot(df, aes(x, y)) +
175+
geom_point() +
176+
facet_grid(f1 ~ f2, scales = "free") +
177+
guides(x.sec = "axis", y.sec = "axis") +
178+
theme(
179+
axis.text.y.left = element_text(hjust = 0),
180+
axis.text.y.right = element_text(hjust = 1),
181+
axis.text.x.top = element_text(vjust = 1),
182+
axis.text.x.bottom = element_text(vjust = 0)
183+
)
184+
185+
expect_doppelganger("outside-justified labels", p)
186+
})

0 commit comments

Comments
 (0)