geom_textbox() a lot in my recent data visualisations, but, every time, I end up resorting to a bit of trial and error to get the alignment just right. Time to create a cheatsheet that will be useful to my future self, and hopefully to a few others also.
I like it for its versatility. It allows for fun things with markdown and a limited number of html tags, which makes it easy to format the text on the fly. I’ll demo a few tricks in the code below but cover them in more detail elsewhere. It also allows for easy placement and manipulation of the box itself, tweaking the radius of the corners, the colour, how thick the border is, and many more things.
What are the alignment parameters?
These can be set per textbox using values within aes() to allow for different alignments for different textboxes, or across the board outside of aes() so that the same alignment settings are applied to all the textboxes. In this demo, I’ll set different values for each box.
OK, let’s go!
First, we need to load the necessary libraries:
library(tidyverse) library(ggtext) library(extrafont)
Next, let’s put a tibble together to provide data for our textboxes.
alignments <- tibble("h_align" = sort(rep(c(0, 0.5, 1), 3)), "h_just" = rep(c(0, 0.5, 1), 3), "v_align" = rep(c(0, 0.5, 1), 3), "v_just" = sort(rep(c(0, 0.5, 1), 3))) %>% mutate("content" = paste0("<span style=\"font-size:36px\">↕</span> **vjust = ", v_just, ", valign = ", v_align, "**<br>", "<span style=\"font-size:36px\">↔</span> **hjust = ", h_just, ", halign = ", h_align, "**<br><br>", "Here's some text in a box, and *this* is how everything aligns!"))
And finally, let’s create a plot to see how everything aligns.
ggplot(alignments) + geom_textbox(aes(x = h_just, y = v_just, label = content, halign = h_align, hjust = h_just, valign = v_align, vjust = v_just), size = 6.4, colour = "#232a27", box.colour = "#705c70", fill = "#f1f4f3", family = "Lato", width = unit(16, "lines"), height = unit(15, "lines"), lineheight = 1.3, show.legend = F) + geom_point(aes(x = h_just, y = v_just), size = 10, alpha = 0.5, colour = "#232a27") + labs(title = "\ngeom_textbox() alignment cheatsheet", subtitle = "\nThe dots indicate the x/y coordinates of each box", caption = "Graphic: @cararthompson | cararthompson.com\n") + xlim(c(-0.1, 1.1)) + ylim(c(-0.1, 1.1)) + theme_void()%+replace% theme(plot.title = element_text(colour = "#232a27", size = 60, family = "Abel"), plot.subtitle = element_text(colour = "#232a27", size = 40, family = "Lato"), plot.caption = element_text(colour = "#232a27", size = 20, family = "Abel", hjust = 0.95))
So, what does what?
vjustdetermines the alignment of the box against its coordinates
valigndetermines the alignment of the text within the box
valign0 to 1 moves the text from bottom to top and from left to right inside the boxes (huh, that’s the same direction as 0 to 1 on the axes – that should make it easier to remember!)
vjust0 to 1 goes… well I’m not too sure!
I think my confusion around how to verbalise the direction lies in what we use as our reference point. Are we aligning the top of the box to the coordinate, or are we aligning the box to the bottom of the coordinate? If we keep our focus on the bottom/middle top of the box,
vjust = 1 means “make the top of this box line up with the y-coordinate” and the 0 to 1 direction stays consistent with the direction of the y axis. Happy days!
But I think I’ll probably still end up referring back to this plot.