Source code used to generate Hex Stickers for my R packages, using hexSticker.

Requires imageMagick, run: brew install imagemagick.

library(hexSticker)
library(showtext)
library(tidyr)
library(ggplot2)
library(jbplot)

I used https://github.com/ryansafner/hexstickers as a reference to help get started with hexStickers.

rdev

Sticker for rdev.

Uses a modified version of the Wikimedia Commons Infinity in circle symbol to represent DevOps. The fill color is OSHA safety yellow.

font_add_google("Lato")
# TODO: understand why setting dpi = 600 and not dpi = 1200 correctly sizes the font
showtext_opts(dpi = 600)

sticker(
  "assets/infinity.png",
  s_x = 1,
  s_y = 0.7,
  s_width = 0.5,
  s_height = 0.5,
  package = "rdev",
  p_color = "black",
  p_family = "Lato",
  p_size = 28,
  h_fill = "#EAC234",
  h_color = "black",
  filename = "rendered/rdev.png",
  dpi = 1200
)

Rendered file:

jbplot

Sticker for jbplot.

First Version

The background of the sticker is a line plot with three colors using the viridis color map.

j_series <- c(1, 2, 3, 4, 5, 4, 5, 6, 7, 8)

jbplot_v1 <- data.frame(
  observation = 1:10,
  group_a = j_series - 1,
  group_b = j_series + 1,
  group_c = j_series + 3
) |>
  pivot_longer(!observation, names_to = "group") |>
  ggplot(aes(x = observation, y = value, color = group)) +
  geom_line() +
  geom_point() +
  labs(x = NULL, y = NULL) +
  guides(color = "none") +
  scale_x_continuous(labels = NULL) +
  scale_y_continuous(limits = c(-1, 12), labels = NULL) +
  scale_color_viridis_d() +
  theme_quo()

sticker(
  jbplot_v1,
  s_x = 1,
  s_y = 1,
  s_width = 2,
  s_height = 2.15,
  package = "jbplot",
  p_color = "gray50",
  p_family = "Lato",
  p_size = 24,
  h_fill = "white",
  h_color = "black",
  white_around_sticker = TRUE,
  filename = "rendered/jbplot_v1.png",
  dpi = 1200
)

Rendered file:

While this version is OK, it’s strangely unsatisfying.

Second Version

The second version uses a jbplot ggplot_donut() plot with the viridis color map.

jbplot <- data.frame(group = c("A", "B", "C"), n = c(4, 3, 2), stringsAsFactors = FALSE) |>
  ggplot_donut(hsize = 4) +
  scale_fill_viridis_d() +
  guides(fill = "none") +
  theme_transparent() +
  theme(plot.background = element_rect(linewidth = 0))

sticker(
  jbplot,
  s_x = 0.983,
  s_y = 0.6,
  s_width = 1.1,
  s_height = 1.1,
  package = "jbplot",
  p_color = "gray25",
  p_family = "Lato",
  p_size = 22,
  h_fill = "white",
  h_color = "gray50",
  filename = "rendered/jbplot.png",
  dpi = 1200
)

Rendered file:

The second version is more satisfying.

cards

Sticker for cards. Uses ggplot2 text annotations with unicode card suits. The background is Poker Green and the border is Dark Wood.

c_size <- 9
cards <- ggplot() +
  annotate("text", x = 1, y = 0, label = "A\u2663", size = c_size) +
  annotate("text", x = 2, y = 0, label = "A\u2666", size = c_size, color = "red") +
  annotate("text", x = 3, y = 0, label = "A\u2665", size = c_size, color = "red") +
  annotate("text", x = 4, y = 0, label = "A\u2660", size = c_size) +
  annotate("text", x = 5, y = 0, label = "K\u2663", size = c_size) +
  scale_x_continuous(limits = c(0.25, 5.75)) +
  theme_void() +
  theme_transparent()

sticker(
  cards,
  s_x = 1,
  s_y = 0.65,
  s_width = 2,
  s_height = 2,
  package = "cards",
  p_y = 1.2,
  p_color = "#FFFFFF",
  p_family = "Lato",
  p_size = 22,
  h_fill = "#35654D",
  h_color = "#855E42",
  filename = "rendered/cards.png",
  dpi = 1200
)

Rendered file:

quantrr

Sticker for quantrr. Features an uppercase “Q” in the Metropolis font, rendered as a .png since Metropolis isn’t in Google Fonts. Blue Q, orange text, with a dark gray border and light gray background.

pal <- jbplot::differently_palettes$primary

sticker(
  "assets/q-logo.png",
  s_x = 1,
  s_y = 1.3,
  s_width = 0.5,
  s_height = 0.5,
  package = "quantrr",
  p_y = 0.7,
  p_color = pal[["orange"]],
  p_family = "Lato",
  p_size = 20,
  h_fill = pal[["lightgray"]],
  h_color = pal[["darkgray"]],
  filename = "rendered/quantrr.png",
  dpi = 1200
)

Rendered file:

stickers

Stickers image built with the hexwall script. Because hexwall() uses a white background, the sticker background is also white. The border and title are Royal Blue.

hexwall("analysis/rendered", sticker_row_size = 2)
sticker(
  "assets/hexwall.png",
  s_x = 1,
  s_y = 0.625,
  s_width = 0.4,
  s_height = 0.4,
  package = "stickers",
  p_color = "#2B60DE",
  p_family = "Lato",
  p_size = 18,
  h_fill = "white",
  h_color = "#2B60DE",
  filename = "rendered/stickers.png",
  dpi = 1200
)

Rendered file:

LS0tCnRpdGxlOiBIZXggU3RpY2tlcnMKYXV0aG9yOiBKb2huIEJlbm5pbmdob2ZmCmRhdGU6ICcyMDIzLTAyLTAxJwpkYXRlLW1vZGlmaWVkOiAnMjAyNC0xMS0xNicKY2F0ZWdvcmllczogc3RpY2tlcnMKb3JkZXI6IDEwMQpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRoZW1lOgogICAgICB2ZXJzaW9uOiA1CiAgICAgIHByZXNldDogYm9vdHN0cmFwCiAgICBjc3M6IGFzc2V0cy9leHRyYS5jc3MKICAgIHBhbmRvY19hcmdzOiAtLXNoaWZ0LWhlYWRpbmctbGV2ZWwtYnk9MQogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiBubwogICAgICBzbW9vdGhfc2Nyb2xsOiBubwotLS0KClNvdXJjZSBjb2RlIHVzZWQgdG8gZ2VuZXJhdGUgSGV4IFN0aWNrZXJzIGZvciBteSBSIHBhY2thZ2VzLCB1c2luZyBbaGV4U3RpY2tlcl0oaHR0cHM6Ly9naXRodWIuY29tL0d1YW5nY2h1YW5nWXUvaGV4U3RpY2tlcikuCgpSZXF1aXJlcyBpbWFnZU1hZ2ljaywgcnVuOiBgYnJldyBpbnN0YWxsIGltYWdlbWFnaWNrYC4KCmBgYHtyIHNldHVwLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0KbGlicmFyeShoZXhTdGlja2VyKQpsaWJyYXJ5KHNob3d0ZXh0KQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoamJwbG90KQpgYGAKCkkgdXNlZCA8aHR0cHM6Ly9naXRodWIuY29tL3J5YW5zYWZuZXIvaGV4c3RpY2tlcnM+IGFzIGEgcmVmZXJlbmNlIHRvIGhlbHAgZ2V0IHN0YXJ0ZWQgd2l0aApoZXhTdGlja2Vycy4KCiMgcmRldgoKU3RpY2tlciBmb3IgW3JkZXZdKGh0dHBzOi8vamFiZW5uaW5naG9mZi5naXRodWIuaW8vcmRldi8pLgoKVXNlcyBhIG1vZGlmaWVkIHZlcnNpb24gb2YgdGhlIFdpa2ltZWRpYSBDb21tb25zCltJbmZpbml0eSBpbiBjaXJjbGVdKGh0dHBzOi8vY29tbW9ucy53aWtpbWVkaWEub3JnL3dpa2kvRmlsZTpJbmZpbml0eV9pbl9jaXJjbGUuc3ZnKSBzeW1ib2wgdG8KcmVwcmVzZW50IFtEZXZPcHNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Rldk9wc190b29sY2hhaW4pLiBUaGUgZmlsbCBjb2xvciBpcwpbT1NIQSBzYWZldHkgeWVsbG93XShodHRwczovL2hleHRvcmFsLmNvbS9oZXgtY29sb3IvZWFjMjM0L2ZlZGVyYWwtc3RkLTU5NWMvKS4KCmBgYHtyIHJkZXZ9CmZvbnRfYWRkX2dvb2dsZSgiTGF0byIpCiMgVE9ETzogdW5kZXJzdGFuZCB3aHkgc2V0dGluZyBkcGkgPSA2MDAgYW5kIG5vdCBkcGkgPSAxMjAwIGNvcnJlY3RseSBzaXplcyB0aGUgZm9udApzaG93dGV4dF9vcHRzKGRwaSA9IDYwMCkKCnN0aWNrZXIoCiAgImFzc2V0cy9pbmZpbml0eS5wbmciLAogIHNfeCA9IDEsCiAgc195ID0gMC43LAogIHNfd2lkdGggPSAwLjUsCiAgc19oZWlnaHQgPSAwLjUsCiAgcGFja2FnZSA9ICJyZGV2IiwKICBwX2NvbG9yID0gImJsYWNrIiwKICBwX2ZhbWlseSA9ICJMYXRvIiwKICBwX3NpemUgPSAyOCwKICBoX2ZpbGwgPSAiI0VBQzIzNCIsCiAgaF9jb2xvciA9ICJibGFjayIsCiAgZmlsZW5hbWUgPSAicmVuZGVyZWQvcmRldi5wbmciLAogIGRwaSA9IDEyMDAKKQpgYGAKClJlbmRlcmVkIGZpbGU6CgohW10ocmVuZGVyZWQvcmRldi5wbmcpCgojIGpicGxvdAoKU3RpY2tlciBmb3IgW2picGxvdF0oaHR0cHM6Ly9qYWJlbm5pbmdob2ZmLmdpdGh1Yi5pby9qYnBsb3QvKS4KCiMjIEZpcnN0IFZlcnNpb24KClRoZSBiYWNrZ3JvdW5kIG9mIHRoZSBzdGlja2VyIGlzIGEgbGluZSBwbG90IHdpdGggdGhyZWUgY29sb3JzIHVzaW5nIHRoZQpbdmlyaWRpc10oaHR0cHM6Ly9zam1nYXJuaWVyLmdpdGh1Yi5pby92aXJpZGlzLykgY29sb3IgbWFwLgoKYGBge3IgamJwbG90X3YxfQpqX3NlcmllcyA8LSBjKDEsIDIsIDMsIDQsIDUsIDQsIDUsIDYsIDcsIDgpCgpqYnBsb3RfdjEgPC0gZGF0YS5mcmFtZSgKICBvYnNlcnZhdGlvbiA9IDE6MTAsCiAgZ3JvdXBfYSA9IGpfc2VyaWVzIC0gMSwKICBncm91cF9iID0gal9zZXJpZXMgKyAxLAogIGdyb3VwX2MgPSBqX3NlcmllcyArIDMKKSB8PgogIHBpdm90X2xvbmdlcighb2JzZXJ2YXRpb24sIG5hbWVzX3RvID0gImdyb3VwIikgfD4KICBnZ3Bsb3QoYWVzKHggPSBvYnNlcnZhdGlvbiwgeSA9IHZhbHVlLCBjb2xvciA9IGdyb3VwKSkgKwogIGdlb21fbGluZSgpICsKICBnZW9tX3BvaW50KCkgKwogIGxhYnMoeCA9IE5VTEwsIHkgPSBOVUxMKSArCiAgZ3VpZGVzKGNvbG9yID0gIm5vbmUiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IE5VTEwpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtMSwgMTIpLCBsYWJlbHMgPSBOVUxMKSArCiAgc2NhbGVfY29sb3JfdmlyaWRpc19kKCkgKwogIHRoZW1lX3F1bygpCgpzdGlja2VyKAogIGpicGxvdF92MSwKICBzX3ggPSAxLAogIHNfeSA9IDEsCiAgc193aWR0aCA9IDIsCiAgc19oZWlnaHQgPSAyLjE1LAogIHBhY2thZ2UgPSAiamJwbG90IiwKICBwX2NvbG9yID0gImdyYXk1MCIsCiAgcF9mYW1pbHkgPSAiTGF0byIsCiAgcF9zaXplID0gMjQsCiAgaF9maWxsID0gIndoaXRlIiwKICBoX2NvbG9yID0gImJsYWNrIiwKICB3aGl0ZV9hcm91bmRfc3RpY2tlciA9IFRSVUUsCiAgZmlsZW5hbWUgPSAicmVuZGVyZWQvamJwbG90X3YxLnBuZyIsCiAgZHBpID0gMTIwMAopCmBgYAoKUmVuZGVyZWQgZmlsZToKCiFbXShyZW5kZXJlZC9qYnBsb3RfdjEucG5nKQoKV2hpbGUgdGhpcyB2ZXJzaW9uIGlzIE9LLCBpdCdzIHN0cmFuZ2VseSB1bnNhdGlzZnlpbmcuCgojIyBTZWNvbmQgVmVyc2lvbgoKVGhlIHNlY29uZCB2ZXJzaW9uIHVzZXMgYSBqYnBsb3QKW2BnZ3Bsb3RfZG9udXQoKWBdKGh0dHBzOi8vamFiZW5uaW5naG9mZi5naXRodWIuaW8vamJwbG90L3JlZmVyZW5jZS9nZ3Bsb3RfZG9udXQuaHRtbCkgcGxvdCB3aXRoIHRoZQpbdmlyaWRpc10oaHR0cHM6Ly9zam1nYXJuaWVyLmdpdGh1Yi5pby92aXJpZGlzLykgY29sb3IgbWFwLgoKYGBge3IgamJwbG90fQpqYnBsb3QgPC0gZGF0YS5mcmFtZShncm91cCA9IGMoIkEiLCAiQiIsICJDIiksIG4gPSBjKDQsIDMsIDIpLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpIHw+CiAgZ2dwbG90X2RvbnV0KGhzaXplID0gNCkgKwogIHNjYWxlX2ZpbGxfdmlyaWRpc19kKCkgKwogIGd1aWRlcyhmaWxsID0gIm5vbmUiKSArCiAgdGhlbWVfdHJhbnNwYXJlbnQoKSArCiAgdGhlbWUocGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGxpbmV3aWR0aCA9IDApKQoKc3RpY2tlcigKICBqYnBsb3QsCiAgc194ID0gMC45ODMsCiAgc195ID0gMC42LAogIHNfd2lkdGggPSAxLjEsCiAgc19oZWlnaHQgPSAxLjEsCiAgcGFja2FnZSA9ICJqYnBsb3QiLAogIHBfY29sb3IgPSAiZ3JheTI1IiwKICBwX2ZhbWlseSA9ICJMYXRvIiwKICBwX3NpemUgPSAyMiwKICBoX2ZpbGwgPSAid2hpdGUiLAogIGhfY29sb3IgPSAiZ3JheTUwIiwKICBmaWxlbmFtZSA9ICJyZW5kZXJlZC9qYnBsb3QucG5nIiwKICBkcGkgPSAxMjAwCikKYGBgCgpSZW5kZXJlZCBmaWxlOgoKIVtdKHJlbmRlcmVkL2picGxvdC5wbmcpCgpUaGUgc2Vjb25kIHZlcnNpb24gaXMgbW9yZSBzYXRpc2Z5aW5nLgoKIyBjYXJkcwoKU3RpY2tlciBmb3IgW2NhcmRzXShodHRwczovL2phYmVubmluZ2hvZmYuZ2l0aHViLmlvL2NhcmRzLykuIFVzZXMgZ2dwbG90MiB0ZXh0IGFubm90YXRpb25zIHdpdGgKW3VuaWNvZGUgY2FyZCBzdWl0c10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUGxheWluZ19jYXJkc19pbl9Vbmljb2RlKS4gVGhlIGJhY2tncm91bmQgaXMKW1Bva2VyIEdyZWVuXShodHRwczovL2NvbG9yLXJlZ2lzdGVyLm9yZy9jb2xvci9wb2tlci1ncmVlbikgYW5kIHRoZSBib3JkZXIgaXMKW0RhcmsgV29vZF0oaHR0cHM6Ly9jb2xvci1yZWdpc3Rlci5vcmcvY29sb3IvZGFyay13b29kKS4KCmBgYHtyIGNhcmRzfQpjX3NpemUgPC0gOQpjYXJkcyA8LSBnZ3Bsb3QoKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMSwgeSA9IDAsIGxhYmVsID0gIkFcdTI2NjMiLCBzaXplID0gY19zaXplKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDAsIGxhYmVsID0gIkFcdTI2NjYiLCBzaXplID0gY19zaXplLCBjb2xvciA9ICJyZWQiKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMywgeSA9IDAsIGxhYmVsID0gIkFcdTI2NjUiLCBzaXplID0gY19zaXplLCBjb2xvciA9ICJyZWQiKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gNCwgeSA9IDAsIGxhYmVsID0gIkFcdTI2NjAiLCBzaXplID0gY19zaXplKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gNSwgeSA9IDAsIGxhYmVsID0gIktcdTI2NjMiLCBzaXplID0gY19zaXplKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMC4yNSwgNS43NSkpICsKICB0aGVtZV92b2lkKCkgKwogIHRoZW1lX3RyYW5zcGFyZW50KCkKCnN0aWNrZXIoCiAgY2FyZHMsCiAgc194ID0gMSwKICBzX3kgPSAwLjY1LAogIHNfd2lkdGggPSAyLAogIHNfaGVpZ2h0ID0gMiwKICBwYWNrYWdlID0gImNhcmRzIiwKICBwX3kgPSAxLjIsCiAgcF9jb2xvciA9ICIjRkZGRkZGIiwKICBwX2ZhbWlseSA9ICJMYXRvIiwKICBwX3NpemUgPSAyMiwKICBoX2ZpbGwgPSAiIzM1NjU0RCIsCiAgaF9jb2xvciA9ICIjODU1RTQyIiwKICBmaWxlbmFtZSA9ICJyZW5kZXJlZC9jYXJkcy5wbmciLAogIGRwaSA9IDEyMDAKKQpgYGAKClJlbmRlcmVkIGZpbGU6CgohW10ocmVuZGVyZWQvY2FyZHMucG5nKQoKIyBxdWFudHJyCgpTdGlja2VyIGZvciBbcXVhbnRycl0oaHR0cHM6Ly9qYWJlbm5pbmdob2ZmLmdpdGh1Yi5pby9xdWFudHJyLykuIEZlYXR1cmVzIGFuIHVwcGVyY2FzZSAiUSIgaW4gdGhlCltNZXRyb3BvbGlzXShodHRwczovL3d3dy4xMDAxZm9udHMuY29tL21ldHJvcG9saXMtZm9udC5odG1sKSBmb250LCByZW5kZXJlZCBhcyBhIGAucG5nYCBzaW5jZQpNZXRyb3BvbGlzIGlzbid0IGluIEdvb2dsZSBGb250cy4gQmx1ZSBRLCBvcmFuZ2UgdGV4dCwgd2l0aCBhIGRhcmsgZ3JheSBib3JkZXIgYW5kIGxpZ2h0IGdyYXkKYmFja2dyb3VuZC4KCmBgYHtyIHF1YW50cnJ9CnBhbCA8LSBqYnBsb3Q6OmRpZmZlcmVudGx5X3BhbGV0dGVzJHByaW1hcnkKCnN0aWNrZXIoCiAgImFzc2V0cy9xLWxvZ28ucG5nIiwKICBzX3ggPSAxLAogIHNfeSA9IDEuMywKICBzX3dpZHRoID0gMC41LAogIHNfaGVpZ2h0ID0gMC41LAogIHBhY2thZ2UgPSAicXVhbnRyciIsCiAgcF95ID0gMC43LAogIHBfY29sb3IgPSBwYWxbWyJvcmFuZ2UiXV0sCiAgcF9mYW1pbHkgPSAiTGF0byIsCiAgcF9zaXplID0gMjAsCiAgaF9maWxsID0gcGFsW1sibGlnaHRncmF5Il1dLAogIGhfY29sb3IgPSBwYWxbWyJkYXJrZ3JheSJdXSwKICBmaWxlbmFtZSA9ICJyZW5kZXJlZC9xdWFudHJyLnBuZyIsCiAgZHBpID0gMTIwMAopCmBgYAoKUmVuZGVyZWQgZmlsZToKCiFbXShyZW5kZXJlZC9xdWFudHJyLnBuZykKCiMgc3RpY2tlcnMKClN0aWNrZXJzIGltYWdlIGJ1aWx0IHdpdGggdGhlIGBoZXh3YWxsYApbc2NyaXB0XShodHRwczovL2dpdGh1Yi5jb20vbWl0Y2hlbGxvaGFyYXdpbGQvaGV4d2FsbC9ibG9iL2YzZTY3YTk2OGQ5NzJiZjZiYzg2OTIzZjA5ODVkZWQ0NjRiN2I4Y2QvaGV4d2FsbC5SKS4KQmVjYXVzZSBgaGV4d2FsbCgpYCB1c2VzIGEgd2hpdGUgYmFja2dyb3VuZCwgdGhlIHN0aWNrZXIgYmFja2dyb3VuZCBpcyBhbHNvIHdoaXRlLiBUaGUgYm9yZGVyIGFuZAp0aXRsZSBhcmUgW1JveWFsIEJsdWVdKGh0dHBzOi8vY29sb3ItcmVnaXN0ZXIub3JnL2NvbG9yL3JveWFsLWJsdWUpLgoKYGBgcgpoZXh3YWxsKCJhbmFseXNpcy9yZW5kZXJlZCIsIHN0aWNrZXJfcm93X3NpemUgPSAyKQpgYGAKCmBgYHtyIHN0aWNrZXJzfQpzdGlja2VyKAogICJhc3NldHMvaGV4d2FsbC5wbmciLAogIHNfeCA9IDEsCiAgc195ID0gMC42MjUsCiAgc193aWR0aCA9IDAuNCwKICBzX2hlaWdodCA9IDAuNCwKICBwYWNrYWdlID0gInN0aWNrZXJzIiwKICBwX2NvbG9yID0gIiMyQjYwREUiLAogIHBfZmFtaWx5ID0gIkxhdG8iLAogIHBfc2l6ZSA9IDE4LAogIGhfZmlsbCA9ICJ3aGl0ZSIsCiAgaF9jb2xvciA9ICIjMkI2MERFIiwKICBmaWxlbmFtZSA9ICJyZW5kZXJlZC9zdGlja2Vycy5wbmciLAogIGRwaSA9IDEyMDAKKQpgYGAKClJlbmRlcmVkIGZpbGU6CgohW10ocmVuZGVyZWQvc3RpY2tlcnMucG5nKQo=