绘图轴标题上的工具提示

Tooltip on plotly axis title

我想在绘图的轴标题上显示工具提示。

这是我的尝试:

x <- y <- 1:10
dat <- expand.grid(x=x, y=y)
dat <- transform(dat, z=x*y)

jscode <- '
$(document).ready(function(){
  setTimeout(function(){
    $($("#heatmap .g-xtitle text")[0]).attr("title", "hello").attr("data-toggle", "tooltip");
  }, 5000);
})
'

library(shiny)
library(plotly)
shinyApp(
  ui <- fluidPage(
    tags$head(tags$script(jscode)),
    plotlyOutput("heatmap")
  ),
  server = function(input, output){
    output$heatmap <- renderPlotly(plot_ly() %>%
      add_trace(data=dat, x=~x, y=~y, z=~z, type="heatmap") %>%
      layout(
        xaxis = list(title="foo") 
      )
    )
  }
)

JS 代码按预期将属性 data-toggletitle 设置为 x-axis 标题的容器,但没有出现工具提示。我还在控制台中尝试了类似 $($("#heatmap .g-xtitle text")[0]).tooltip() 的操作,但没有任何反应。

注意:很遗憾,我还没有解决您的问题,但希望这些信息对您有所帮助。祝你好运!

背景:SVG

  1. plotly 创建图为 Scalable Vector Graphics (<svg>)

  2. <svg> 的工具提示必须添加为 child element named <title>

  3. <title>应该是其parent

  4. first child element
  5. 新增<svg>个元素需要created in the SVG namespace

SVG 工具提示:矩形与绘图 x-axis

作为概念证明,我在您的示例中添加了一个 <svg> 矩形。然后我使用 JS 添加了一个 <title> 元素作为 <rect> 元素的第一个 child,它在矩形上生成了一个工具提示。

然而,对 plotly 热图执行相同的步骤不会在 x-axis 标题上生成工具提示,尽管 <title> 元素已添加到 x-axis标题容器。

代码

library(shiny)
library(plotly)

x <- y <- 1:10
dat <- expand.grid(x=x, y=y)
dat <- transform(dat, z=x*y)

### Create a <svg> rectangle element
testRect <- '<svg width="250" height="75" xmlns="http://www.w3.org/2000/svg">
                <g class="test-rect">
                    <rect x="10" y="10" width="200" height="50" 
                        style="fill:wheat; stroke:blue; stroke-width:1px"/>
                </g>
            </svg>'

### Add a first child title element to the rectangle <svg>
### Hovering over the rectangle displays the tooltip
jscode_testRect <- '$(document).ready(function(){
    setTimeout(function(){
        var titleRect = document.createElementNS("http://www.w3.org/2000/svg", "title");
        titleRect.textContent = "rectangle tooltip";
        var testRect = document.getElementsByClassName("test-rect")[0];
        testRect.insertBefore(titleRect, testRect.childNodes[0]); 
    }, 500);
});'

### Add a first child title element to the SVG
### Hovering over the x-axis title doesn't display tooltip
jscode_xaxisPlotly <- '$(document).ready(function(){
    setTimeout(function(){
        var titleAxis = document.createElementNS("http://www.w3.org/2000/svg", "title");
        titleAxis.textContent = "x-axis tooltip";
        var gXtitle = document.getElementsByClassName("g-xtitle")[0];
        gXtitle.insertBefore(titleAxis, gXtitle.childNodes[0]); 
    }, 500);
});'

shinyApp(
    ui <- fluidPage(
        tags$head(tags$script(HTML(jscode_testRect))),
        tags$head(tags$script(HTML(jscode_xaxisPlotly))),
        h4("<svg> rectangle - tooltip is functional"),
        tags$div(HTML(testRect)),
        h4("plotly heatmap - tooltip does not work"),
        plotlyOutput("heatmap"),
        br(),
        br()
    ),
    server = function(input, output){
        output$heatmap <- renderPlotly(plot_ly() %>%
                                           add_trace(data=dat, x=~x, y=~y, z=~z, type="heatmap") %>%
                                           layout(
                                               xaxis = list(title="foo"),
                                               title = "Title"
                                           )
        )
    }
)

我认为您的代码有几个问题:

  1. Plotly 不喜欢它的 SVG 代码编辑。即使您定位了正确的元素,Plotly 也可能会立即删除您添加的内容。
  2. 您缺少启用工具提示的代码 app-wise。

当我想将工具提示放在刻度标签上时,我遇到了一个非常相似的问题。我花了很长时间才用自定义 CSS 和 JS 破解它。这个想法是添加一个 div (矩形),它可以完美地覆盖您想要使用工具提示丰富的元素。然后将该矩形的 CSS opacity 设置为 0 以隐藏它。但是一旦您将鼠标悬停在这个矩形上,工具提示就会起作用(即使它是不可见的)。这是一个可视化矩形形状的代码。

x <- y <- 1:10
dat <- expand.grid(x = x, y = y)
dat <- transform(dat, z = x * y)

jscode <- "
$(document).ready(function() {
    // Enable tooltips app-wise
    $(\"[data-toggle='tooltip']\").tooltip({container: 'body'}); 
});
"

csscode <- HTML('
    .plot-container {
        position: relative;
    }
    .xaxis-container {
        height: 20px;
        position:absolute;
        bottom: 0;
        left: 40px;
        background: #bfb9b9;
        opacity: 0.3;
    }
    .xaxis-tooltip {
        width: 30px;
        height: 20px;
        background: #000;
        margin:auto;
    }
')

library(shiny)
library(plotly)
shinyApp(
    ui <- fluidPage(
        tags$head(
            tags$script(jscode),
            tags$style(csscode)
        ),
        div(class = 'plot-container',
            plotlyOutput("heatmap"),
            div(
                class = "xaxis-container",
                div(class = "xaxis-tooltip", "data-toggle" = "tooltip", "title" = "hello")
            )
        )
    ),
    server = function(input, output) {
        output$heatmap <- renderPlotly({
            plot_ly() %>%
                add_trace(
                    data = dat,
                    x =  ~ x,
                    y =  ~ y,
                    z =  ~ z,
                    type = "heatmap"
                ) %>%
                layout(xaxis = list(title = "foo")) %>%
                # We can't just center the rectangle relative to the entire plot area.
                # Instead, we need to do it relative to the draglayer.
                # This code sets proper width of .xaxis-container on app start.
                htmlwidgets::onRender(
                    "
                    function(el, x) {
                        var width = $('.draglayer')[0].getBoundingClientRect().width;
                        $('.xaxis-container').css('width', width);
                    }
                    "
                )
        })
    }
)

将第 21 行中的 opacity: 0.3; 更改为 opacity: 0; 以获得功能齐全的解决方案。