Следующий код работает следующим образом: если мы накрасим и выделим несколько точек, эти точки будут временно окрашены в пурпурный цвет;(если мы щелкнем на панели графика, они будут восстановлены в исходном цвете), затем, если мы нажмем кнопку «активный цвет», эти зачищенные точки будут навсегда превращены в соответствующий выбранный цвет.(если мы нажмем на панель графика, они будут не восстановлены в исходный цвет).
library(ggplot2)
library(shiny)
library(colourpicker)
ui <- fluidPage(
verticalLayout(
actionButton("active_color",
"active color"),
colourInput("color", "color", value = "red", showColour = "background"),
plotOutput("plot", brush = "plot_brush", click = "plot_click"),
verbatimTextOutput("info")
)
)
server <- function(input, output) {
g <- ggplot(mtcars, mapping = aes(x = wt, y = mpg)) + geom_point()
values <- reactiveValues(active_color = 0)
observeEvent(input$active_color, {
values$active_color <- 1
})
observeEvent(input$plot_click, {
values$active_color <- 0
})
output$plot <- renderPlot({
# create ggplot
build <- ggplot_build(g)
len_layer <- length(build$data)
x <- build$data[[len_layer]]$x
y <- build$data[[len_layer]]$y
# brush information
brush_info <- input$plot_brush
id_x <- which(x >= brush_info$xmin & x <= brush_info$xmax)
id_y <- which(y >= brush_info$ymin & y <= brush_info$ymax)
# brush index
id <- intersect(id_x, id_y)
color_vec <- build$data[[len_layer]]$colour
if(length(id) > 0) {
if(values$active_color != 0) {
color_vec[id] <- input$color
g <<- g + geom_point(colour = color_vec)
}
color_vec[id] <-"magenta"
g <- g + geom_point(colour = color_vec)
}
g
})
output$info <- renderPrint({
input$plot_brush
})
}
shinyApp(ui, server)
Код работает нормально.Однако, если я сделаю небольшое изменение в функции сервера.
server <- function(input, output) {
g <- ggplot(mtcars, mapping = aes(x = wt, y = mpg)) + geom_point()
values <- reactiveValues(active_color = 0)
observeEvent(input$active_color, {
values$active_color <- 1
})
observeEvent(input$plot_click, {
values$active_color <- 0
})
output$plot <- renderPlot({
# the change I made here
make_change(g, input, values)
})
output$info <- renderPrint({
input$plot_brush
})
}
make_change <- function(g, input, values) {
build <- ggplot_build(g)
len_layer <- length(build$data)
x <- build$data[[len_layer]]$x
y <- build$data[[len_layer]]$y
# brush information
brush_info <- input$plot_brush
id_x <- which(x >= brush_info$xmin & x <= brush_info$xmax)
id_y <- which(y >= brush_info$ymin & y <= brush_info$ymax)
# brush index
id <- intersect(id_x, id_y)
color_vec <- build$data[[len_layer]]$colour
if(length(id) > 0) {
if(values$active_color != 0) {
color_vec[id] <- input$color
g <<- g + geom_point(colour = color_vec)
}
color_vec[id] <-"magenta"
g <- g + geom_point(colour = color_vec)
}
g
}
Это очень похоже на старую функцию сервера, единственное отличие состоит в том, что я извлекаю весь код в renderPlot
и делаю его новой функциейmake_change
.Если мы запустим, мы обнаружим, что временная выделка (цвет - пурпурный) работает нормально, но постоянное изменение цвета больше не работает.
Кажется, что <<-
хорошо работает в renderPlot()
, однако, он не работает, если находится в функции, а функция в renderPlot()
.
Можно ли заставить второй сервер работать так же, как и первый?Поскольку я хочу написать универсальную функцию, если я использую первую, функция serer слишком длинная, слишком сложная для чтения и изменения.