在UI上,有两个滑块,其中第二个滑块的范围取决于第一个滑块的输入.但是,滑块1上的某些值可能导致滑块2上的锚在末端重叠.有没有办法消除重叠?

谢谢你的帮助.

enter image description here

library(shiny)
library(plotly) 

ui <- fluidPage(
  

  titlePanel("Overlapping anchor"),
  
  sidebarLayout(
   
    sidebarPanel(
      sliderInput("firstSlider", "The first slider", min=0, max=1,value=.7),
      uiOutput("sliderange")
    ),
    
    mainPanel(
      
      tableOutput("values")
      
    )
  )
)

server <- function(input, output) {
  
  sliderValues <- reactive({
    
    data.frame(
      Name = c("First"),
      Value = as.character(c(input$firstSlider)),
      Name = c("Second"),
      Value = as.character(c(input$secondSlider)),
      stringsAsFactors = FALSE)
  })
  
  output$sliderange <- renderUI({
    sliderInput("secondSlider", "The second slider", min = 0, max = round((min(2*input$firstSlider, 2*(1-input$firstSlider))),2), 
                value = min(.1,input$firstSlider, (1-input$firstSlider)), round = -2, step = 0.01)})
  
  output$values <- renderTable({
    sliderValues()
  })
  
}

shinyApp(ui = ui, server = server)

推荐答案

在深入研究了Ion.RangeSlidersliderInput的内部 struct 后,我找到了一个(相当粗糙的)解决方法.

事实证明,对于min/max的某些组合,滴答声的数量被故意设置为非整数.在您的情况下,您可以通过在浏览器中打开开发者工具(Ctrl+Shift+I适用于Windows中的Chrome)并键入以下代码来验证这一点:

$('#secondSlider').data("ionRangeSlider").options.grid_num

在某些情况下,这会导致勾号标签重叠.因此,我们的 idea 是

  1. 检测最后一个记号标签和上一个记号标签之间是否有重叠.
  2. 如果是这样的话,将记号标签的数量四舍五入到下一个整数,这样记号之间的空间就更大了.

因此,需要包含一些javascript,用于重叠检测和调整网格点的数量.最后一点是在"正确"的时间拨打Javascript.也就是说,一旦刷新了被动会话.我们可以用session$onFlushed.为了调用自定义Javascript函数,我们使用ShinyaddCustomMessageHandler pattern.

library(shiny)

js <- paste("function doesOverlap() {",
            "   var $lastLabel = $('#sliderange .irs-grid-text:last');",
            "   var $prevLastLabel = $lastLabel.prevAll('.irs-grid-text').first();",
            "   return $lastLabel.offset().left < $prevLastLabel.offset().left + $prevLastLabel.width();",
            "}\n",
            "Shiny.addCustomMessageHandler('regrid', function(force) {",
            "   if (doesOverlap() | force) {",
            "      console.log('Overlap detected - adjusting tick number');",
            "      var $sld = $('#secondSlider').data('ionRangeSlider');",
            "      var ticks_n = $sld.options.grid_num;",
            "      $sld.update({grid_num: Math.round(ticks_n)});",
            "   }",
            "});", sep = "\n")

ui <- fluidPage(
   tags$head(tags$script(HTML(js), type = "text/javascript")),
   titlePanel("Overlapping anchor"),
   sidebarLayout(
      sidebarPanel(
         sliderInput("firstSlider", "The first slider", min=0, max=1,value=.7),
         uiOutput("sliderange")
      ),
      mainPanel(
         tableOutput("values")
      )
   )
)

server <- function(input, output, session) {
   session$onFlushed(function() {
      session$sendCustomMessage("regrid", FALSE);
   }, FALSE);
   
   sliderValues <- reactive({
      data.frame(
         Name = c("First"),
         Value = as.character(req(input$firstSlider)),
         Name = c("Second"),
         Value = as.character(req(input$secondSlider)),
         stringsAsFactors = FALSE)
   })
   
   output$sliderange <- renderUI({
      sliderInput("secondSlider", "The second slider", 
                  min = 0, max = round(min(2 * input$firstSlider, 
                                           2 * (1 - input$firstSlider)), 2), 
                  value = min(.1, input$firstSlider, (1 - input$firstSlider)), 
                  round = -2, step = 0.01)
   })
   
   output$values <- renderTable({
      sliderValues()
   })
   
}

shinyApp(ui = ui, server = server)

使现代化

在阅读了this question on the Rstudio blog之后,我找到了缺失的部分,以遵循我最初的 idea ,运行滴答号自适应,以响应事件,而不是依赖onFlushed.这样就不需要设置shiny<->;JavaScript接口,可轻松适用于多个react 滑块:

library(shiny)

js <- "
function doesOverlap($sld) {
   var $lastLabel = $sld.parents('.shiny-input-container').find('.irs-grid-text:last');
   var $prevLastLabel = $lastLabel.prevAll('.irs-grid-text').first();
   return $lastLabel.offset().left < $prevLastLabel.offset().left + $prevLastLabel.width();
}

$(document).on({
  'shiny:value': function(event) {
     if (event.name === 'sliderange') { // react upon changes of #sliderange
       // need to defer to next tick to avoid race condition
       setTimeout(function() {
         var $slds = $('.js-range-slider').not('#firstSlider');
         $slds.each(function() {
           if (doesOverlap($(this))) {
              console.log('Overlap detected for element <#' + this.id + '>');
              var $sld = $(this).data('ionRangeSlider');
              var ticks_n = $sld.options.grid_num;
              $sld.update({grid_num: Math.round(ticks_n)});
           }
         });
       }, 0);
     }   
  }
});
"

ui <- fluidPage(
   tags$head(tags$script(HTML(js), type = "text/javascript")),
   titlePanel("Overlapping anchor"),
   sidebarLayout(
      sidebarPanel(
         sliderInput("firstSlider", "The first slider", min=0, max=1,value=.7),
         uiOutput("sliderange")
      ),
      mainPanel(
         tableOutput("values")
      )
   )
)

server <- function(input, output, session) {
   sliderValues <- reactive({
      data.frame(
         Name = c("First"),
         Value = as.character(req(input$firstSlider)),
         Name = c("Second"),
         Value = as.character(req(input$secondSlider)),
         stringsAsFactors = FALSE)
   })
   
   output$sliderange <- renderUI({
      sliderInput("secondSlider", "The second slider", 
                  min = 0, max = round(min(2 * input$firstSlider, 
                                           2 * (1 - input$firstSlider)), 2), 
                  value = min(.1, input$firstSlider, (1 - input$firstSlider)), 
                  round = -2, step = 0.01)
   })
   
   output$values <- renderTable({
      sliderValues()
   })
   
}

shinyApp(ui = ui, server = server)

R相关问答推荐

创建重复删除的唯一数据集组合列表

混淆矩阵,其中每列和等于1

如何使用geom_sf在边界显示两种 colored颜色 ?

使用spatVector裁剪网格数据时出现的问题

保存包含循环和ifelse的函数的输出

selectInput不返回ALL,并将因子转换为shiny 的数字

为什么观察不会被无功值变化触发?

如果第一个列表中的元素等于第二个列表的元素,则替换为第三个列表的元素

在R中使用download. file().奇怪的URL?

在ggplot2中更改小提琴情节的顺序

我正在努力用R计算数据集中的中值逐步距离

如何读取CSV的特定列时,给定标题作为向量

plotly hover文本/工具提示在shiny 中不起作用

如何在科学记数法中显示因子

R -使用矩阵reshape 列表

如何预测原始数据集并将值添加到原始数据集中

创建新列,其中S列的值取决于该行S值是否与其他行冗余

数据集上的R循环和存储模型系数

如果y中存在x中的值,则将y行中的多个值复制到相应的x行中

如何将数据框压缩为更宽,同时将行输入保持为行输入,而不是R中的列名?