Я пытаюсь использовать insertUI для динамического добавления слоя ggplot, включая все его реактивные компоненты (например, aes (x, y), fill, color, alpha).
Я добавил пользовательский интерфейсчерез интерфейс вставки.Я создал уникальный идентификатор # для каждого нового добавленного интерфейса.Мне удалось сохранить каждый Geom в списке реагирующих значений.Хотелось бы воссоздать это на более простом примере:
library(shiny)
library(ggforce)
CircleGeomUI <- function(id) {
ns <- NS(id)
tagList(
fluidRow(
column(3, numericInput(ns("center.x"), "X", value = 0, width = "75px")),
column(3, numericInput(ns("center.y"), "Y", value = 0, width = "75px"))),
fluidRow(sliderInput(ns("radius"),"Select Radius",
min = 1,
max = 100,
value = 10,
width = "75%")
))
}
CircleGeom <- function(input, output, session) {
geom_circle(mapping = aes(x0=input$center.x,
y0=input$center.y,
r=input$radius)
)
}
TriangleGeomUI <- function(id) {
ns <- NS(id)
tagList(
column(3,
fluidRow(numericInput(ns("a.x"), "a.x", value = 0, width = "75px")),
fluidRow(numericInput(ns("b.x"), "b.x", value = 0, width = "75px")),
fluidRow(numericInput(ns("c.x"), "c.x", value = 10, width = "75px"))),
column(3,
fluidRow(numericInput(ns("a.y"), "a.y", value = 0, width = "75px")),
fluidRow(numericInput(ns("b.y"), "b.y", value = 10, width = "75px")),
fluidRow(numericInput(ns("c.y"), "c.y", value = 0, width = "75px"))))
}
TriangleGeom <- function(input, output, session) {
geom_polygon(mapping = aes(x=c(input$a.x, input$b.x, input$c.x),
y=c(input$a.y, input$b.y, input$c.y)))
}
ui <- fluidPage(
fluidRow(actionButton("add.layer", "+")),
plotOutput("plot"),
tags$div(id = "menu")
)
server <- function(input, output) {
layer.list <- reactiveValues()
observeEvent(input$add.layer, {
layer <- input$add.layer
# setup----
menu <- paste0("shape-menu", layer)
shape <- paste0("shape", layer)
options <- paste0("options", layer)
circle <- paste0("circle", layer)
triangle <- paste0("triangle", layer)
# insert ui----
insertUI(
selector = "#menu",
where = "beforeEnd",
ui = tags$div(
id = menu,
fluidRow(
column(6, selectInput(shape, NULL, choices = c("circle", "triangle"))),
column(6, uiOutput(options))))
)
# render ui----
output[[options]] <- renderUI({
switch(input[[shape]],
"circle" = CircleGeomUI(circle),
"triangle" = TriangleGeomUI(triangle)
)
})
observeEvent(input[[shape]], {
layer.list$gg[[layer]] <- switch(input[[shape]],
"circle" = callModule(CircleGeom, circle),
"triangle" = callModule(TriangleGeom, triangle)
)
})
})
output$plot <- renderPlot({
if(length(layer.list$gg) == 0) {
x <- ggplot()
} else {
x <- ggplot() %+% layer.list$gg
}
return(x)
})
}
shinyApp(ui, server)
У меня есть три проблемы:
Я могу хранить геомы только в списке реагирующих значений внутри наблюдаемого события.Я думаю, что это должно быть лениво, поэтому я бы хотел, чтобы это было в ответной реакции.Не работает.
Использование кнопки действия «add.layer» приводит к начальному предупреждению: Предупреждение: Ошибка в: Все столбцы в таблице должны быть объектами 1d или 2d:
- Столбец
x0
равен NULL - Столбец
y0
равен NULL - Столбец
r
равен NULL Вызов rlang::last_error()
для просмотра обратного следа 189:
Я не знаю, почему это появляется.Я не знаю, как упорядочить реактивность блеска или замедлить ее, чтобы отображаемый интерфейс мог появляться первым.Я не знаю, как прочитать след.
Это самая большая и самая странная проблема.Код, кажется, работает, когда координаты x / y находятся внутри «aes» в каждом geom.Когда я создаю data.frame и просто ссылаюсь на data.frame a la 'aes (x = x, y = y)', он не работает.Когда я добавляю реактивный ввод для альфа, заливки или цвета вне сопоставления, он также завершается неудачей.
Это проблема реактивности, проблема ggplot или что-то еще?Можно ли вообще кодировать в виде блеска?