Переключение цветов ввода слайдера без мерцания - PullRequest
0 голосов
/ 26 мая 2018

Я пытаюсь заставить блестящее приложение переключать цвета ввода слайдера при определенных условиях вместе с обновлением.Пример ниже демонстрирует несовершенную версию того, что я пытаюсь сделать.Он просто имеет ползунковый ввод и две кнопки.Две кнопки используют функцию 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 находится в конце вопроса, поскольку его содержание менее актуально)

В быстрой системе результаты выглядят хорошо, поскольку между выполнением строк имеется небольшая задержка.Однако, если я переключаюсь на более медленную машину, вы можете увидеть, что ползунок мигает обратно к своему первоначальному синему цвету при переключении между цветами, предоставляемыми type1 и type2.Это происходит потому, что updateSliderInput удаляет все классы, добавленные в слайдер вручную при применении его собственных обновлений.Я ищу способ предотвратить это.Я подозреваю, что это может быть сделано с помощью session$sendCustomMessage или session$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 голосов
/ 07 июня 2018

Если вы посмотрите на код javsacript в глянцевом для обновления ввода ползунка (файл input_binding_slider.js), блестящий вызовет функцию API собственной библиотеки ползунка, чтобы выполнить обновление.Я только что попытался запустить эту строку обновления самостоятельно в консоли javascript, и она действительно очищает любые пользовательские классы (я подозреваю, что это не просто очистка класса, а скорее всего, это просто перестройка HTML и не заботится о том, чтобы попытаться сохранить какой-либо случайный неожиданный результат).добавленные классы).

У меня нет прекрасного идеального решения для вас, но есть несколько альтернативных вариантов, которые вам могут или не нравятся:

Решение 1: добавьте классв родительский div для ввода и немного измените свой CSS-селектор соответственно (мое рекомендуемое решение)

Решение 2: вместо updateSliderInput используйте uiOutput + renderUI, а в renderUI вы можете сгенерировать ввод слайдера, которыйуже имеет данный класс, когда он собирается (используя htmltools::tagAppendAttributes()) (больше работы, но может работать)

Решение 3: используйте свой собственный javascript для обновления и немедленно добавьте класс (не рекомендуется)

Примечание. Мне не удалось воспроизвести проблему мерцания, поэтому я на самом деле неЯ заметил, что конкретная проблема решена, но я подозреваю, что это может помочь.

Примечание 2: я думаю, что delay(0, ...) подойдет, я не думаю, что вам нужно ставить положительное число там

0 голосов
/ 29 мая 2018

Вместо того, чтобы добавлять классы и пытаться предотвратить их перезапись updateSliderInput, можно по желанию переключать цвет ползунка по умолчанию, чтобы не было мерцания, как показано в приведенном ниже коде.

Примечаниечто этот подход все еще имеет свои проблемы.Например, если вы пишете модуль, основанный на этом, я не знаю простого способа определения идентификатора для вашего собственного слайдера, чтобы вы могли правильно редактировать окраску по умолчанию.

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