Skip to content

Commit

Permalink
Axis alignment over multiple panels (#5826)
Browse files Browse the repository at this point in the history
* Don't fix viewport size

* add null padding

* Fix viewport size, but flexibly

* add test

* add news bullet
  • Loading branch information
teunbrand committed Aug 20, 2024
1 parent 1a6e495 commit 2071c97
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 1 deletion.
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# ggplot2 (development version)

* Axis labels are now justified across facet panels (@teunbrand, #5820)
* Fixed bug in `stat_function()` so x-axis title now produced automatically
when no data added. (@phispu, #5647).
* geom_sf now accepts shape names (@sierrajohnson, #5808)
Expand Down
18 changes: 17 additions & 1 deletion R/guide-axis.R
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ GuideAxis <- ggproto(
# Unlist the 'label' grobs
z <- if (params$position == "left") c(2, 1, 3) else 1:3
z <- rep(z, c(1, length(grobs$labels), 1))
has_labels <- !is.zero(grobs$labels[[1]])
grobs <- c(list(grobs$ticks), grobs$labels, list(grobs$title))

# Initialise empty gtable
Expand All @@ -445,10 +446,25 @@ GuideAxis <- ggproto(
vp <- exec(
viewport,
!!params$orth_aes := unit(params$orth_side, "npc"),
!!params$orth_size := params$measure_gtable(gt),
!!params$orth_size := max(params$measure_gtable(gt), unit(1, "npc")),
just = params$opposite
)

# Add null-unit padding to justify based on eventual gtable cell shape
# rather than dimensions of this axis alone.
if (has_labels && params$position %in% c("left", "right")) {
where <- layout$l[-c(1, length(layout$l))]
just <- with(elements$text, rotate_just(angle, hjust, vjust))$hjust %||% 0.5
gt <- gtable_add_cols(gt, unit(just, "null"), pos = min(where) - 1)
gt <- gtable_add_cols(gt, unit(1 - just, "null"), pos = max(where) + 1)
}
if (has_labels && params$position %in% c("top", "bottom")) {
where <- layout$t[-c(1, length(layout$t))]
just <- with(elements$text, rotate_just(angle, hjust, vjust))$vjust %||% 0.5
gt <- gtable_add_rows(gt, unit(1 - just, "null"), pos = min(where) - 1)
gt <- gtable_add_rows(gt, unit(just, "null"), pos = max(where) + 1)
}

# Assemble with axis line
absoluteGrob(
gList(axis_line, gt),
Expand Down
144 changes: 144 additions & 0 deletions tests/testthat/_snaps/facet-labels/outside-justified-labels.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions tests/testthat/test-facet-labels.R
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,30 @@ test_that("parsed labels are rendered correctly", {
facet_wrap(~ f, labeller = label_parsed)
)
})

test_that("outside-justified labels are justified across panels", {

df <- data.frame(
x = c("X\nX\nX\nX\nX", "X"),
y = c("YYYYY", "Y"),
f1 = c("A", "B"),
f2 = c("C", "D")
)

# By default, axis labels are inside-justified so it doesn't matter whether
# justification occurs across panels. This changes for outside-justification.
# See #5820

p <- ggplot(df, aes(x, y)) +
geom_point() +
facet_grid(f1 ~ f2, scales = "free") +
guides(x.sec = "axis", y.sec = "axis") +
theme(
axis.text.y.left = element_text(hjust = 0),
axis.text.y.right = element_text(hjust = 1),
axis.text.x.top = element_text(vjust = 1),
axis.text.x.bottom = element_text(vjust = 0)
)

expect_doppelganger("outside-justified labels", p)
})

0 comments on commit 2071c97

Please sign in to comment.