1

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

enter image description here

but is lost with ggplotly:

ggplotly(pp)

enter image description here

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

1 Answer 1

1

ggplotly() removes line breaks

What 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.

Create an R function to modify the plotly object

Fortunately, once you know what the problem is, it's easy to fix from R, without using any html, js or css. Simply:

  1. Line wrap.
  2. Replace all \n with <br>.
  3. Make all text in the form "**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:

Plot with line breaks and bold

Sign up to request clarification or add additional context in comments.

2 Comments

thanks, that an interesting work around although its still missing the bold legend titles, would you know how to add them?
@user63230 I missed that was part of the question but sure - see my edit.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.