I've spent a good deal of time trying to figure out how to customize or control the legend behavior of Plotly when using Plotly's highlight()
feature in combination with plotly::ggplotly()
. Here is an example:
library(ggplot2)
library(plotly)
library(dplyr)
test_data <- data.frame(
name = LETTERS[1:5],
metric = sample(x = c(500:800), size = 100)
) %>%
arrange(name) %>%
group_by(name) %>%
mutate(index = row_number()) %>%
data.frame()
plotly_obj <- ggplotly(
test_data %>%
highlight_key(~name) %>%
ggplot() +
geom_line(
aes(
x = index,
y = metric,
color = name
),
size = .75
) +
scale_x_continuous(breaks = c(1:20)) +
scale_color_brewer(palette = "Accent") +
theme_bw()
)
highlight(
plotly_obj,
on = "plotly_hover",
off = "plotly_doubleclick",
opacityDim = .1
) %>%
config(displayModeBar = F)
This produces a chart that is very close to what I'm looking for, however, the legend reacts to the hover highlighting by adding a second instance of the group being highlighted in the legend:
I found a way to completely disable the legend behavior with highlight
by adding selected = attrs_selected(showlegend = FALSE)
inside the function above (after the opacityDim = .1
line), which produces the following:
Is there a way to force the legend to highlight the group/line that is currently selected via hover inside the legend instead of either 1.) creating a duplicate highlighted item in the legend like the first chart or 2.) completely disabling the legend in the second chart? I'm by no means an expert with Plotly, and I have a feeling my issues may be the result of my ignorance regarding Plotly's crosstalk mechanic and possibly not understanding how ggplotly
is passing the aes()
features to the legend. However, I know very little JavaScript, and I have yet to find a way to force the legend to behave this way. Please let me know if I'm missing something.
Unfortunately the current highlight implementation of plotly cannot support what you want. Under the hood, R plotly adds a new line (trace) to the graph and dims all the other lines. Rather then updating the actual style of the individual lines. See the javascript code where this happens:
I opened a github issue on this with the request to change the behaviour how it is currently implemented: https://github.com/plotly/plotly.R/issues/2417
However, as stated in the issue, the solution to fix this is not straight forward as in general highlights do not necessarily have to cover the whole original trace data. Meaning in that case we still want to see the legend entries.
As for how to then solve your problem. If you use plotly in a static site (like R markdown report) i am afraid that this cannot get solved.
If you are using shiny. You could implement the highlighting yourself by invoking the "restyle" method using plotlyProxy.
The downside is that you have will have to create the plotly object directly from individual traces (and not ggplotly) and perform trace bookmarking to know what is selected and what is deselected.
The other downside is that the highlighting then does not happen only client side anymore. But round-trip communication with shiny needs to happen. Depending on your server load and the amount of graphs, this can also not be desirable.