添加自定义模式栏按钮以允许按颜色实现第三种悬停模式的功能

问题描述 投票:0回答:1

这希望是我对这个情节的最后一个问题。我之前收到过两次帮助,两次都在独立的绘图中工作,但我的绘图对象出现在一个闪亮的应用程序的上下文中提出了其他问题。

Kat 提出了两种解决方案:这里

  1. 对 HTML 按钮的第一次修复导致绘图在每次更改闪亮输入时添加一个按钮,因此这不是一个好的修复。
  2. 带有绘图按钮的第二个解决方案效果很好,但在循环不同的悬停选项时似乎存在问题。 “按颜色悬停”选项将仅卡在其中一种颜色上,并且不再随鼠标移动。

希望找到适合我的用例的解决方案,但需要自定义事件处理程序所需的 JavaScript 帮助来替换我当前拥有的“悬停时按颜色比较”的函数

{hovermode = 'x'}

本质上,我希望将按颜色悬停功能作为新的自定义模式栏按钮的选项。

数据:

library(shiny)
library(tidyverse)
library(plotly)
library(bslib)
library(htmlwidgets)

dat <- data.frame(group1=(rep(letters[1:4], each=5)), 
           group2=rep(LETTERS[1:5], times=4),
           pct = c(rep(.2, times=5), 
                   c(.1, .1, .1, .3, .4), 
                   c(.2, .2, .2, .3, .1),
                   c(.3, .1, .2, .2, .2))
)

创建自定义按钮:

closest <- list(
  name = "Show closest data on hover",
  icon = list(
    width = 1792,
    height = 1792,
    path = "M1203 544q0 13-10 23l-393 393 393 393q10 10 10 23t-10 23l-50 50q-10 10-23 10t-23-10l-466-466q-10-10-10-23t10-23l466-466q10-10 23-10t23 10l50 50q10 10 10 23z",
    transform = 'matrix(1 0 0 -1 0 1792)'
    ),
  click = htmlwidgets::JS(
    "function(gd) {
       Plotly.relayout(gd, {hovermode: 'closest'});
    }"
  )
)

colorcompare <- list(
  name = "Compare by color on hover",
  icon = list(
    width = 1792,
    height = 1792,
    path = "M1011 1376q0 13-10 23l-50 50q-10 10-23 10t-23-10l-466-466q-10-10-10-23t10-23l466-466q10-10 23-10t23 10l50 50q10 10 10 23t-10 23l-393 393 393 393q10 10 10 23zm384 0q0 13-10 23l-50 50q-10 10-23 10t-23-10l-466-466q-10-10-10-23t10-23l466-466q10-10 23-10t23 10l50 50q10 10 10 23t-10 23l-393 393 393 393q10 10 10 23z",
    transform = 'matrix(1 0 0 -1 0 1792)'
    ),
  click = htmlwidgets::JS(
    "function(gd) {
      Plotly.relayout(gd, {hovermode: 'x'});
    }"
  )
)

ycompare <- list(
  name = "Compare y data on hover",
  icon = list(
    width = 1792,
    height = 1792,
    path = "M1395 864q0 13-10 23l-466 466q-10 10-23 10t-23-10l-466-466q-10-10-10-23t10-23l50-50q10-10 23-10t23 10l393 393 393-393q10-10 23-10t23 10l50 50q10 10 10 23zm0-384q0 13-10 23l-466 466q-10 10-23 10t-23-10l-466-466q-10-10-10-23t10-23l50-50q10-10 23-10t23 10l393 393 393-393q10-10 23-10t23 10l50 50q10 10 10 23z",
    transform = 'matrix(1 0 0 -1 0 1792)'
    ),
  click = htmlwidgets::JS(
    "function(gd) {
      Plotly.relayout(gd, {hovermode: 'y'});
    }"
  )
)

最后,剧情:

plot <- dat %>%
  plot_ly() %>%
  add_bars(x = ~pct, y = ~group1,  color = ~group2,
           split = ~group2, customdata = ~group2,
           hovertemplate = paste0("%{x:.2f%}<br>", "<extra>%{customdata}</extra>")) %>% 
  layout(yaxis = list(title = 'Group 1', autorange = 'reversed', categoryorder = 'trace'),
         xaxis = list(title = 'Percent', tickformat = ".0%"),
         barmode = 'stack', hovermode = 'y', legend = list(traceorder = "normal")) %>%
  config(displaylogo = FALSE, modeBarButtonsToAdd = list(closest, colorcompare, ycompare),
         modeBarButtonsToRemove = list('hoverCompareCartesian','hoverClosestCartesian')) 

plot
r shiny plotly htmlwidgets stacked-bar-chart
1个回答
0
投票

我不确定这会如何影响你的 Shiny 应用程序中的其他内容 - 但是,如果没有 Shiny,这将起作用。

这会向主体添加一个类名称,然后每当您悬停时都会检查该类是否指示需要按颜色进行比较。

点击功能

closest

  click = htmlwidgets::JS(
    "function(gd) {
      document.querySelector('body').classList.replace('byColor', 'no');
      Plotly.relayout(gd, {hovermode: 'closest'});
    }"
  )

colorcompare

  click = htmlwidgets::JS(
    "function(gd) {
      document.querySelector('body').classList.replace('no', 'byColor');
      Plotly.relayout(gd, {hovermode: 'closest'});
    }"
  )

ycompare

  click = htmlwidgets::JS(
    "function(gd) {
      document.querySelector('body').classList.replace('byColor', 'no');
      Plotly.relayout(gd, {hovermode: 'y'});
    }"
  )

最后获取需要与您的绘图相匹配的

colorcompare
悬停和
onRender
调用的数据:

  onRender(
    "function(el, x) {
      document.querySelector('body').classList.add('no');
      el.on('plotly_hover', function(d) {
        if(document.querySelector('body').classList.contains('byColor')) {
          tellMe = d.points[0].pointNumber;      /* changes by color */
          gimme = d.points[0].curveNumber;       /* stays the same by color */
          let xlen = el.data[0].x.length;        /* number of stacked bars */
          let thatsIt = [];
          for(i = 0; i < xlen; i++) {            /* make a hover for each bar */
            thatsIt.push({curveNumber: gimme, pointNumber: i})
          }
          Plotly.Fx.hover(el.id, thatsIt);
        }
      });
    }")

graph

© www.soinside.com 2019 - 2024. All rights reserved.