切换滑块输入颜色而不闪烁

时间:2018-05-26 07:52:17

标签: r shiny shinyjs

我正在尝试制作一个闪亮的应用程序在特定条件下切换滑块输入的颜色以及更新。下面的例子演示了我想要做的不完美版本。它只有一个滑块输入和两个按钮。这两个按钮使用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;
}

2 个答案:

答案 0 :(得分:1)

不是处理添加类并试图阻止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')

))

server.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;
}

答案 1 :(得分:1)

如果你看一下闪亮的javsacript代码来更新滑块输入(input_binding_slider.js文件),闪亮会调用滑块自己的库的API函数来进行更新。我只是尝试在javascript控制台中运行这个更新行,它确实清除了任何自定义类(我怀疑它不是字面上清除类,而是它可能只是重建HTML而不是&#39 ; t关心尝试保留任何已添加的随机意外类。

我没有为您提供完美的解决方案,但您可能会或可能不喜欢其他一些选择:

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

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

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

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

注2:我认为delay(0, ...)会这样做,我认为你不需要在那里加上正数