Skip to content

Improvements to geom_label() #5030

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
Apr 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
59850ac
Merge pull request #1 from tidyverse/master
teunbrand Jan 13, 2021
86787de
Merge branch 'tidyverse:master' into master
teunbrand Sep 15, 2021
1d1a2b0
Merge branch 'tidyverse:main' into master
teunbrand Mar 24, 2022
28eff54
Merge branch 'tidyverse:main' into master
teunbrand May 11, 2022
a60ff00
Merge branch 'tidyverse:main' into master
teunbrand Sep 14, 2022
6f25aba
Merge branch 'tidyverse:main' into master
teunbrand Nov 3, 2022
d3e934f
Use `angle` aesthetic in `geom_label()`
teunbrand Nov 5, 2022
457c89d
Add news bullet
teunbrand Nov 5, 2022
80b8b56
Revert unnecessary clip argument
teunbrand Nov 5, 2022
2c3ddb8
Add rotation test
teunbrand Nov 5, 2022
f209d37
Update docs
teunbrand Nov 5, 2022
9828157
Use text descenders
teunbrand Nov 5, 2022
940566e
Interpret "lines" unit correctly
teunbrand Nov 5, 2022
186dffc
Accept visual change
teunbrand Nov 5, 2022
0fd4b05
Update news bullet
teunbrand Nov 5, 2022
c29b36e
Merge branch 'main' into geom_label_angle
teunbrand Nov 7, 2022
52badfc
Merge branch 'main' into geom_label_angle
teunbrand Jan 3, 2023
2570d0d
Use titleGrob for label
teunbrand Jan 16, 2023
f2f22bf
Allow margin as padding
teunbrand Jan 16, 2023
c0604a9
Decommission makeContent method
teunbrand Jan 16, 2023
19c5fe8
Merge branch 'geom_label_angle' of https://github.com/teunbrand/ggplo…
teunbrand Jan 16, 2023
8b7d10e
Merge branch 'main' into geom_label_angle
teunbrand Jan 16, 2023
b2644ef
Merge branch 'geom_label_angle' of https://github.com/teunbrand/ggplo…
teunbrand Jan 16, 2023
9eaabfc
Edit NEWS bullet
teunbrand Jan 16, 2023
2012c41
Update test
teunbrand Jan 16, 2023
4217c8e
Merge branch 'main' into geom_label_angle
teunbrand Apr 15, 2023
04a6754
Merge branch 'main' into geom_label_angle
teunbrand Apr 21, 2023
4258fa2
Merge branch 'main' into geom_label_angle
teunbrand Apr 21, 2023
1ad3d89
improve details
teunbrand Apr 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ S3method(limits,POSIXlt)
S3method(limits,character)
S3method(limits,factor)
S3method(limits,numeric)
S3method(makeContent,labelgrob)
S3method(makeContext,dotstackGrob)
S3method(merge_element,default)
S3method(merge_element,element)
Expand Down
6 changes: 6 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# ggplot2 (development version)

* `geom_label()` now uses the `angle` aesthetic (@teunbrand, #2785)
* 'lines' units in `geom_label()`, often used in the `label.padding` argument,
are now are relative to the text size. This causes a visual change, but fixes
a misalignment issue between the textbox and text (@teunbrand, #4753)
* The `label.padding` argument in `geom_label()` now supports inputs created
with the `margin()` function (#5030).
* As an internal change, the `titleGrob()` has been refactored to be faster.
* The `translate_shape_string()` internal function is now exported for use in
extensions of point layers (@teunbrand, #5191).
Expand Down
55 changes: 31 additions & 24 deletions R/geom-label.R
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ GeomLabel <- ggproto("GeomLabel", Geom,
if (is.character(data$hjust)) {
data$hjust <- compute_just(data$hjust, data$x)
}
if (!inherits(label.padding, "margin")) {
label.padding <- rep(label.padding, length.out = 4)
}

grobs <- lapply(1:nrow(data), function(i) {
row <- data[i, , drop = FALSE]
Expand All @@ -85,6 +88,7 @@ GeomLabel <- ggproto("GeomLabel", Geom,
just = c(row$hjust, row$vjust),
padding = label.padding,
r = label.r,
angle = row$angle,
text.gp = gpar(
col = row$colour,
fontsize = row$size * .pt,
Expand All @@ -109,7 +113,7 @@ GeomLabel <- ggproto("GeomLabel", Geom,

labelGrob <- function(label, x = unit(0.5, "npc"), y = unit(0.5, "npc"),
just = "center", padding = unit(0.25, "lines"), r = unit(0.1, "snpc"),
default.units = "npc", name = NULL,
angle = NULL, default.units = "npc", name = NULL,
text.gp = gpar(), rect.gp = gpar(fill = "white"), vp = NULL) {

if (length(label) != 1) {
Expand All @@ -121,32 +125,35 @@ labelGrob <- function(label, x = unit(0.5, "npc"), y = unit(0.5, "npc"),
if (!is.unit(y))
y <- unit(y, default.units)

gTree(label = label, x = x, y = y, just = just, padding = padding, r = r,
name = name, text.gp = text.gp, rect.gp = rect.gp, vp = vp, cl = "labelgrob")
}
if (!is.null(angle) & is.null(vp)) {
vp <- viewport(
angle = angle, x = x, y = y,
width = unit(0, "cm"), height = unit(0, "cm"),
gp = gpar(fontsize = text.gp$fontsize)
)
x <- unit(rep(0.5, length(x)), "npc")
y <- unit(rep(0.5, length(y)), "npc")
}

#' @export
makeContent.labelgrob <- function(x) {
hj <- resolveHJust(x$just, NULL)
vj <- resolveVJust(x$just, NULL)

t <- textGrob(
x$label,
x$x + 2 * (0.5 - hj) * x$padding,
x$y + 2 * (0.5 - vj) * x$padding,
just = c(hj, vj),
gp = x$text.gp,
name = "text"
descent <- font_descent(
text.gp$fontfamily, text.gp$fontface, text.gp$fontsize, text.gp$cex
)
hjust <- resolveHJust(just, NULL)
vjust <- resolveVJust(just, NULL)

text <- titleGrob(
label = label, hjust = hjust, vjust = vjust, x = x, y = y,
margin = padding, margin_x = TRUE, margin_y = TRUE,
gp = text.gp
)

r <- roundrectGrob(x$x, x$y, default.units = "native",
width = grobWidth(t) + 2 * x$padding,
height = grobHeight(t) + 2 * x$padding,
just = c(hj, vj),
r = x$r,
gp = x$rect.gp,
name = "box"
box <- roundrectGrob(
x = x, y = y - (1 - vjust) * descent,
width = widthDetails(text),
height = heightDetails(text),
just = c(hjust, vjust),
r = r, gp = rect.gp, name = "box"
)

setChildren(x, gList(r, t))
gTree(children = gList(box, text), name = name, vp = vp)
}
6 changes: 3 additions & 3 deletions R/geom-text.R
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
#'
#' @eval rd_aesthetics("geom", "text")
#' @section `geom_label()`:
#' Currently `geom_label()` does not support the `check_overlap` argument
#' or the `angle` aesthetic. Also, it is considerably slower than `geom_text()`.
#' The `fill` aesthetic controls the background colour of the label.
#' Currently `geom_label()` does not support the `check_overlap` argument. Also,
#' it is considerably slower than `geom_text()`. The `fill` aesthetic controls
#' the background colour of the label.
#'
#' @section Alignment:
#' You can modify text alignment with the `vjust` and `hjust`
Expand Down
6 changes: 3 additions & 3 deletions man/geom_text.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions tests/testthat/test-geom-label.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,23 @@ test_that("geom_label() throws meaningful errors", {
expect_snapshot_error(geom_label(position = "jitter", nudge_x = 0.5))
expect_snapshot_error(labelGrob(label = 1:3))
})

test_that("geom_label() rotates labels", {
df <- data_frame0(
x = 1:5,
y = 1,
lab = c("cat", "dog", "banana", "orange", "tea")
)

angle_in <- c(0, 45, 90, 135, 180)

p <- ggplot(df, aes(x, y, label = lab)) +
geom_label(angle = angle_in)

vps <- lapply(
layer_grob(p, 1)[[1]]$children,
`[[`, "vp"
)
angle_out <- unname(vapply(vps, `[[`, numeric(1), "angle"))
expect_equal(angle_in, angle_out)
})