rplotlyplotly.js

Individual marker.line is not always refelcted in the legend


Disclaimer. I am working with R but the question is actually a general plotly question (I am just faster generating a plot in R than in vanilla JS).

I have the following code, which adds a border around the bar on hover. This works as expected, BUT the legend changes only if I hover over (and thus border) the first bar of the trace.

I would like that either it does not change at all (preferred solution), or the border is added to the legend irrespective of which bar of the trace I am hovering over.

library(plotly)
library(htmlwidgets)
set.seed(29042025)
d <- expand.grid(a = LETTERS[1:3], b = letters[1:2])
d$c <- sample(10, 6)

plot_ly(d) %>%
  add_bars(x = ~ c, y = ~ a, color = ~ b) %>%
  onRender("function(el, x) {
   el.on('plotly_hover', function(data){
     const color = Array(3).fill('undefined');
     const width = Array(3).fill('undefined');
     const pos = data.points[0].pointNumber;
     color[pos] = 'black';
     width[pos] = 2;
     Plotly.restyle(el, {'marker.line': null});
     Plotly.restyle(el, {'marker.line.color': [color], 'marker.line.width': [width]}, [data.points[0].curveNumber]);
   });
  }")

Solution

  • If you inspect the legend paths whilst hovering over the traces, you can see that the style.strokeWidth changes if you hover over the first bars of the trace. it changes the strokeWidth to 2px which we don't want!

    out1

    so all we have to do is to force this style.strokeWidth = '0px'; of the legend.elements (with class="legendundefined") on plotly.hover:

    library(plotly)
    library(htmlwidgets)
    set.seed(29042025)
    d <- expand.grid(a = LETTERS[1:3], b = letters[1:2])
    d$c <- sample(10, 6)
    
    plot_ly(d) %>%
      add_bars(x = ~ c, y = ~ a, color = ~ b) %>%
      onRender("function(el, x) {
       el.on('plotly_hover', function(data){
         const color = Array(3).fill('undefined');
         const width = Array(3).fill('undefined');
         const pos = data.points[0].pointNumber;
         color[pos] = 'black';
         width[pos] = 2;
         Plotly.restyle(el, {'marker.line': null});
         Plotly.restyle(el, {'marker.line.color': [color], 'marker.line.width': [width]}, [data.points[0].curveNumber]);
         el.querySelectorAll('.legendundefined').forEach((element) => {
            element.style.strokeWidth = '0px';
          });
       });
      }")
    

    giving

    out2