【问题标题】:Switching slider input colors without flickering切换滑块输入颜色而不闪烁
【发布时间】:2018-06-07 10:19:53
【问题描述】:

我正在尝试制作一个闪亮的应用程序在某些条件下切换滑块输入的颜色以及更新。下面的示例演示了我正在尝试做的一个不完美的版本。它只有一个滑块输入和两个按钮。这两个按钮使用updateSliderInput 函数来更改滑块的一些属性,然后我使用shinyjs 向滑块添加一个类,使其颜色发生变化。

ui.R

library(shiny)
library(shinyjs)

shinyUI(fluidPage(
    includeCSS('www/style.css'),
    useShinyjs(),
    sliderInput("slider",
                "A slider",
                min = 1,
                max = 50,
                value = 30),
    actionButton('type1','type 1'),
    actionButton('type2','type 2')

))

server.R

library(shiny)
library(shinyjs)

shinyServer(function(input, output,session) {

    observeEvent(input$type1,{
        updateSliderInput(session,
                          inputId = 'slider',
                          min = 0,
                          value = 10,
                          max = 20)
        delay(3,{
            removeClass(selector = '.js-irs-0', class = 'type2')
            addClass(selector = '.js-irs-0', class = 'type1')
        })
    })

    observeEvent(input$type2,{
        updateSliderInput(session,
                          inputId = 'slider',
                          min = 0,
                          value = 20,
                          max = 40)
        delay(3,{
            removeClass(selector = '.js-irs-0', class = 'type1')
            addClass(selector = '.js-irs-0', class = 'type2')
        })
    })

})

(www/css 文件位于问题的末尾,因为它的内容不太相关)

在快速系统中,结果看起来不错,因为执行行之间几乎没有延迟。但是,如果我切换到速度较慢的机器,当在type1type2 提供的颜色之间切换时,您会看到滑块闪烁回原来的蓝色。发生这种情况是因为updateSliderInput 在应用自己的更新时删除了手动添加到滑块的任何类。我正在寻找一种方法来防止这种情况发生。我怀疑可以使用session$sendCustomMessagesession$sendInputMessage 来完成,但到目前为止我还没有成功。

注意:delay 函数是必要的,因为没有它,updateSliderInput 会覆盖 addClass 执行的更改。 removeClass 不是绝对必要的,因为 updateSliderInput 已经删除了手动添加的类,但我保留了这条线,因为修复可能涉及阻止 updateSliderInput 这样做。

如约而至:

www/style.css

.type1 .irs-bar {
border-top-color: #8B1A1A;
border-bottom-color: #8B1A1A;
}

.type1 .irs-bar-edge {
border-color: #8B1A1A;
}

.type1 .irs-single, .type1 .irs-bar-edge, .type1 .irs-bar {
background: #8B1A1A;
}

.type2 .irs-bar {
border-top-color: #6959CD;
border-bottom-color: #6959CD;
}

.type2 .irs-bar-edge {
border-color: #6959CD;
}

.type2 .irs-single, .type2 .irs-bar-edge, .type2 .irs-bar {
background: #6959CD;
}

【问题讨论】:

    标签: r shiny shinyjs


    【解决方案1】:

    如果您查看 shiny 中用于更新滑块输入(input_binding_slider.js 文件)的 javsacript 代码,shiny 会调用滑块自己的库的 API 函数来进行更新。我只是尝试自己在javascript控制台中运行此更新行,它确实清除了所有自定义类(我怀疑它并没有真正清除类,而是它可能只是重建HTML并且不关心尝试保留任何随机意外添加的类)。

    我没有适合您的完美解决方案,但有一些您可能喜欢也可能不喜欢的替代方案:

    解决方案 1:将类添加到输入的父 div,并相应地稍微更改您的 CSS 选择器(我推荐的解决方案)

    解决方案 2:使用 uiOutput+renderUI 代替 updateSliderInput,并且在 renderUI 中,您可以生成一个在构建时已经具有给定类的滑块输入(使用htmltools::tagAppendAttributes())(更多工作但可以工作)

    解决方案3:使用自己的javascript进行更新并立即添加类(不推荐)

    注意:我无法复制闪烁问题,因此我实际上并未检查具体问题是否已解决,但我怀疑它可能会有所帮助。

    注意 2:我认为 delay(0, ...) 可以,我认为您不需要在此处输入正数

    【讨论】:

    • 切换到此作为解决方案 1 的答案允许在模块中使用,这与我在下面的帖子不同
    【解决方案2】:

    无需处理添加类并试图阻止updateSliderInput 覆盖它们,而是可以随意切换滑块的默认颜色,这样就不会发生闪烁,如下面的代码所示。

    请注意,这种方法仍然存在问题。例如,如果您正在编写一个依赖于此的模块,我不知道有一种简单的方法可以检测您自己的滑块的 id 是什么,以便您可以正确编辑默认颜色。

    ui.R

    library(shiny)
    
    shinyUI(fluidPage(
        includeCSS('www/type1.css'), # your initial look
        htmlOutput('defaultSlider'), # update to change colors
        sliderInput("slider",
                    "A slider",
                    min = 1,
                    max = 50,
                    value = 30),
        actionButton('type1','type 1'),
        actionButton('type2','type 2')
    
    ))
    

    服务器.R

    library(shiny)
    
    shinyServer(function(input, output,session) {
    
    
        observeEvent(input$type1,{
            updateSliderInput(session,
                              inputId = 'slider',
                              min = 0,
                              value = 10,
                              max = 20)
    
            output$defaultSlider = renderUI({
                includeCSS('www/type1.css')
            })
        })
    
        observeEvent(input$type2,{
            updateSliderInput(session,
                              inputId = 'slider',
                              min = 0,
                              value = 20,
                              max = 40)
    
            output$defaultSlider = renderUI({
                includeCSS('www/type2.css')
            })
        })
    })
    

    www/type1.css

    .js-irs-0 .irs-bar {
        border-top-color: #8B1A1A;
            border-bottom-color: #8B1A1A;
    }
    
    .js-irs-0 .irs-bar-edge {
        border-color: #8B1A1A;
    }
    
    .js-irs-0 .irs-single, .js-irs-0 .irs-bar-edge, .js-irs-0 .irs-bar {
        background: #8B1A1A;
    }
    

    www/type2.css

    .js-irs-0 .irs-bar {
        border-top-color: #6959CD;
            border-bottom-color: #6959CD;
    }
    
    .js-irs-0 .irs-bar-edge {
        border-color: #6959CD;
    }
    
    .js-irs-0 .irs-single, .js-irs-0 .irs-bar-edge, .js-irs-0 .irs-bar {
        background: #6959CD;
    }
    

    【讨论】:

      猜你喜欢
      • 2011-01-06
      • 2015-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-17
      • 2012-06-23
      • 2015-06-22
      • 2018-04-17
      相关资源
      最近更新 更多