plotly:点击图例中的点时突出显示(暗淡),而不是过滤

plotly: highlight (dim), rather than filter, when clicking on point in legend

我正在用 R 构建情节图。这些图有图例。每个图例都有一个代表数据级别的彩色点。这是一个最小的例子:

library(plotly)
data(iris)
plot_ly(
  x     = ~Petal.Length, y = ~Petal.Width, 
  color = ~Species,
  data  = iris)

默认情况下,双击图例中的一个点会完全隐藏所有不相关的点。例如,双击图例中的 "versicolor" 点会隐藏绘图中的所有 "setosa" 和 "virginica" 点。在 plotly argot 中,它 "filters" 图中的数据。

但我宁愿单击图例中的某个点 突出显示 图中的点。例如,我想单击(或双击)图例中的 versicolor 点来使图中的 "setosa" 和 "virginica" 点变暗,也许是通过降低它们的不透明度。图中的杂色点将是 "highlighted." 这种行为可以实现吗?

我已通读 plotly 文档并在 SO 和 plotly 论坛中搜索相关问题。该搜索提出了两种可能的解决方案,但它们看起来相当复杂:

这些是最好的方法吗?如果是,并且不止一个可行,我应该追求哪一个?

其他说明:我没有使用 Shiny。我知道 itemclickitemdoubleclick 图例属性,以及 highlight_key(),但它们似乎不相关。 (如有不妥请指正)

关键是在 R 中禁用图例单击事件,然后编写一个自定义事件处理程序,在触发 plotly_legendclick 时更改图形。这是一个例子:

library(plotly)
data(iris)
myPlot <- plot_ly(
  x     = ~Petal.Length, y = ~Petal.Width, 
  color = ~Species,
  data  = iris)

# Disable default click-on-legend behavior
myPlot <- layout(
  myPlot, 
  legend = list(itemclick = FALSE, itemdoubleclick = FALSE))

# Add an event handler
onRender(
  myPlot,
  "function (el) {
    const OPACITY_START = el._fullData[0].marker.opacity;
    const OPACITY_DIM   = 0.3;
    el.on('plotly_legendclick', function (data) {

      // Get current opacity. The legend bubble on which we click is given by 
      // data.curveNumber: data.curveNumber == 0 means that we clicked on the 
      // first bubble, 1 means that we clicked on the second bubble, and so on.
      var currentOpacity = data.fullData[data.curveNumber].marker.opacity

      if (currentOpacity < OPACITY_START) {                 // if points already dimmed
        var update = { 'marker.opacity' : OPACITY_START };    // could also set to null
      } else {                                              // if points not already dimmed
        var update = { 'marker.opacity' : OPACITY_DIM }; 
      }

      Plotly.restyle(el, update, data.curveNumber);
        } );
    }"
)

当用户单击图例气泡时,此代码会在 "normal" 和 "dim" 状态之间切换绘图中的相应气泡。

要切换绘图中的 other 气泡——也就是说,要修改其他轨迹——需要进行小的修改。特别是,data.curveNumber 始终是与图例中单击的气泡对应的迹线编号。要改为修改其他迹线,我们需要将其他迹线编号传递给 Plotly.restyle(),而不是 data.curveNumber 索引的迹线。有关这一点的更多信息,请参阅 Plotly.restyle() documentation