Skip to content

Commit cb39362

Browse files
authored
Improvements to geom_label() (#5030)
* Use `angle` aesthetic in `geom_label()` * Add news bullet * Revert unnecessary clip argument * Add rotation test * Update docs * Use text descenders * Interpret "lines" unit correctly * Accept visual change * Update news bullet * Use titleGrob for label * Allow margin as padding * Decommission makeContent method * Edit NEWS bullet * Update test * improve details
1 parent 90de384 commit cb39362

File tree

7 files changed

+64
-32
lines changed

7 files changed

+64
-32
lines changed

NAMESPACE

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ S3method(limits,POSIXlt)
109109
S3method(limits,character)
110110
S3method(limits,factor)
111111
S3method(limits,numeric)
112-
S3method(makeContent,labelgrob)
113112
S3method(makeContext,dotstackGrob)
114113
S3method(merge_element,default)
115114
S3method(merge_element,element)

NEWS.md

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

3+
* `geom_label()` now uses the `angle` aesthetic (@teunbrand, #2785)
4+
* 'lines' units in `geom_label()`, often used in the `label.padding` argument,
5+
are now are relative to the text size. This causes a visual change, but fixes
6+
a misalignment issue between the textbox and text (@teunbrand, #4753)
7+
* The `label.padding` argument in `geom_label()` now supports inputs created
8+
with the `margin()` function (#5030).
39
* As an internal change, the `titleGrob()` has been refactored to be faster.
410
* The `translate_shape_string()` internal function is now exported for use in
511
extensions of point layers (@teunbrand, #5191).

R/geom-label.R

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ GeomLabel <- ggproto("GeomLabel", Geom,
7676
if (is.character(data$hjust)) {
7777
data$hjust <- compute_just(data$hjust, data$x)
7878
}
79+
if (!inherits(label.padding, "margin")) {
80+
label.padding <- rep(label.padding, length.out = 4)
81+
}
7982

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

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

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

124-
gTree(label = label, x = x, y = y, just = just, padding = padding, r = r,
125-
name = name, text.gp = text.gp, rect.gp = rect.gp, vp = vp, cl = "labelgrob")
126-
}
128+
if (!is.null(angle) & is.null(vp)) {
129+
vp <- viewport(
130+
angle = angle, x = x, y = y,
131+
width = unit(0, "cm"), height = unit(0, "cm"),
132+
gp = gpar(fontsize = text.gp$fontsize)
133+
)
134+
x <- unit(rep(0.5, length(x)), "npc")
135+
y <- unit(rep(0.5, length(y)), "npc")
136+
}
127137

128-
#' @export
129-
makeContent.labelgrob <- function(x) {
130-
hj <- resolveHJust(x$just, NULL)
131-
vj <- resolveVJust(x$just, NULL)
132-
133-
t <- textGrob(
134-
x$label,
135-
x$x + 2 * (0.5 - hj) * x$padding,
136-
x$y + 2 * (0.5 - vj) * x$padding,
137-
just = c(hj, vj),
138-
gp = x$text.gp,
139-
name = "text"
138+
descent <- font_descent(
139+
text.gp$fontfamily, text.gp$fontface, text.gp$fontsize, text.gp$cex
140+
)
141+
hjust <- resolveHJust(just, NULL)
142+
vjust <- resolveVJust(just, NULL)
143+
144+
text <- titleGrob(
145+
label = label, hjust = hjust, vjust = vjust, x = x, y = y,
146+
margin = padding, margin_x = TRUE, margin_y = TRUE,
147+
gp = text.gp
140148
)
141149

142-
r <- roundrectGrob(x$x, x$y, default.units = "native",
143-
width = grobWidth(t) + 2 * x$padding,
144-
height = grobHeight(t) + 2 * x$padding,
145-
just = c(hj, vj),
146-
r = x$r,
147-
gp = x$rect.gp,
148-
name = "box"
150+
box <- roundrectGrob(
151+
x = x, y = y - (1 - vjust) * descent,
152+
width = widthDetails(text),
153+
height = heightDetails(text),
154+
just = c(hjust, vjust),
155+
r = r, gp = rect.gp, name = "box"
149156
)
150157

151-
setChildren(x, gList(r, t))
158+
gTree(children = gList(box, text), name = name, vp = vp)
152159
}

R/geom-text.R

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@
2525
#'
2626
#' @eval rd_aesthetics("geom", "text")
2727
#' @section `geom_label()`:
28-
#' Currently `geom_label()` does not support the `check_overlap` argument
29-
#' or the `angle` aesthetic. Also, it is considerably slower than `geom_text()`.
30-
#' The `fill` aesthetic controls the background colour of the label.
28+
#' Currently `geom_label()` does not support the `check_overlap` argument. Also,
29+
#' it is considerably slower than `geom_text()`. The `fill` aesthetic controls
30+
#' the background colour of the label.
3131
#'
3232
#' @section Alignment:
3333
#' You can modify text alignment with the `vjust` and `hjust`

man/geom_text.Rd

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/_snaps/geom-sf/labels-for-north-carolina.svg

Lines changed: 1 addition & 1 deletion
Loading

tests/testthat/test-geom-label.R

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,23 @@ test_that("geom_label() throws meaningful errors", {
22
expect_snapshot_error(geom_label(position = "jitter", nudge_x = 0.5))
33
expect_snapshot_error(labelGrob(label = 1:3))
44
})
5+
6+
test_that("geom_label() rotates labels", {
7+
df <- data_frame0(
8+
x = 1:5,
9+
y = 1,
10+
lab = c("cat", "dog", "banana", "orange", "tea")
11+
)
12+
13+
angle_in <- c(0, 45, 90, 135, 180)
14+
15+
p <- ggplot(df, aes(x, y, label = lab)) +
16+
geom_label(angle = angle_in)
17+
18+
vps <- lapply(
19+
layer_grob(p, 1)[[1]]$children,
20+
`[[`, "vp"
21+
)
22+
angle_out <- unname(vapply(vps, `[[`, numeric(1), "angle"))
23+
expect_equal(angle_in, angle_out)
24+
})

0 commit comments

Comments
 (0)