I want to wrap the text of the legend for the following plot, which works with ggplot
:
library(tidyverse)
library(ggtext)
library(plotly)
df <- data.frame(xx = c(0, 3),
yy = c(0, 1))
df_text <- data.frame(start = c(0, 1, 2),
end = c(1, 2, 3),
heading_bold = c("title 1", "title 2", "title 3"),
normal_text = c("i want this to be normal text title 1 but it is also a very long title that i want to wrap",
"i want this to be normal text title 2 but it is also a very long title that i want to wrap",
"i want this to be normal text title 3 but it is also a very long title that i want to wrap")) %>%
mutate(merged_text = paste0("**",heading_bold,"**: ", normal_text))
pp <- ggplot(df, aes(x = xx, y = yy)) +
geom_rect(data = df_text,
aes(xmin = start,
xmax = end,
fill = merged_text,
ymin = 0,
ymax = 1),
inherit.aes = FALSE) +
scale_fill_viridis_d(option = "A", name = "Legend",
limits = unique(df_text$merged_text), direction = -1,
labels = function(x) str_replace_all(str_wrap(x, width = 30), "\\n", "<br>")) +
theme(legend.text = element_markdown())
pp
but is lost with ggplotly
:
ggplotly(pp)
I am sure there is clever way of applying css
/html
styling to achieve this (without writing out the full legend text again) - any ideas?
thanks
ggplotly()
removes line breaksWhat is happening here is actually that the new lines are lost when you convert to a plotly
object. You can see this here:
ggpl <- ggplotly(pp)
ggpl$x$data[[1]]$name
# [1] "**title 1**: i want this to be normal text title 1 but it is also a very long title that i want to wrap"
As you can see, the <br>
blocks you faithfully added have disappeared. I thought this might be to do with plotly
escaping html, but even if you use htmltools::HTML("<br>")
, the same thing happens.
plotly
objectFortunately, once you know what the problem is, it's easy to fix from R, without using any html, js or css. Simply:
\n
with <br>
."**text**"
into <b>text</b>
.add_line_breaks <- function(ggplotly_object, width = 30) {
ggplotly_object$x$data <- lapply(
ggplotly_object$x$data,
\(l) {
l$name <- l$name |>
str_wrap(width = width) |>
str_replace_all("\\n", "<br>") |>
str_replace_all("\\*\\*(.*?)\\*\\*", "<b>\\1</b>")
l
}
)
ggplotly_object
}
Then you can use it as follows:
pp |>
ggplotly() |>
add_line_breaks()
Output: