Немного скорректировал ответ Алекса, чтобы немного улучшить автоматическую компоновку.
max_plots <- 12;
shinyApp(
ui<- pageWithSidebar(
headerPanel("Dynamic number of plots"),
sidebarPanel(width = 2, sliderInput("n", "Number of plots", value=1, min=1, max=max_plots),
h4("Clicked points"),
verbatimTextOutput("click_info"),
h4('click points to see info'),
h4('select area to zoom'),
h4('Double click to unzoom')
),
mainPanel(uiOutput("plots")
)
),
server <- function(input, output) {
ranges <- reactiveValues()
values <- reactiveValues()
output$plots <- renderUI({
plot_output_list <- list()
n <- input$n
n_cols <- if(n == 1) {
1
} else if (n %in% c(2,4)) {
2
} else if (n %in% c(3,5,6,9)) {
3
} else {
4
}
Pwidth <- 900/n_cols
Pheigth <- 600/ceiling(n/n_cols) # calculate number of rows
for(i in 1:ceiling(input$n/n_cols)) {
cols_ <- list();
for(j in 1:round((input$n/n_cols - (i - 1))*n_cols)) {
# print((i-1)*n_cols+j)
n <- (i-1)*n_cols+j
cols_ <- append(cols_,list(column(width = floor(12/n_cols), offset = 0,
# uiOutput(paste('Button', n, sep = '')), ## problem part
plotOutput(paste0("plot", (i-1)*n_cols+j), width = Pwidth, height = Pheigth,
dblclick = paste0("plot", (i-1)*n_cols+j, '_dblclick'),
click = paste0("plot", (i-1)*n_cols+j, '_click'),
brush = brushOpts(
id = paste0("plot", (i-1)*n_cols+j, '_brush'),
resetOnNew = TRUE
))
)));
}
plot_output_list <- append(plot_output_list, list(fluidRow(cols_, style = "width:1000px" )));
}
do.call(tagList, plot_output_list)
})
observe({
lapply(1:input$n, function(i){
plotname <- paste0("plot", i)
output[[plotname]] <- renderPlot({
ggplot(mtcars, aes(wt, mpg, color = as.factor(cyl))) + geom_point() +
coord_cartesian(xlim =ranges[[paste('plot', i, 'x', sep = '')]],
ylim = ranges[[paste('plot', i, 'y', sep = '')]],
# expand = FALSE
) +
theme_classic() +
theme(legend.text=element_text(size=12),
legend.title=element_blank())
})
})
})
# }
output$click_info <- renderPrint({
nearPoints(mtcars, input$plot1_click, addDist = TRUE)
})
# When a double-click happens, check if there's a brush on the plot.
# If so, zoom to the brush bounds; if not, reset the zoom.
lapply(1:max_plots, function(i){
observeEvent(input[[paste('plot', i, '_dblclick', sep = '')]], {
brush <- input[[paste('plot', i, '_brush', sep = '')]]
if (is.null(brush)) {
ranges[[paste('plot', i, 'x', sep = '')]] <- NULL
ranges[[paste('plot', i, 'y', sep = '')]] <- NULL
values[[paste('brushedPoints', i, sep = '')]] <- NULL
}
})
})
lapply(1:max_plots, function(i){
observeEvent(input[[paste('plot', i, '_brush', sep = '')]], {
brush <- input[[paste('plot', i, '_brush', sep = '')]]
if (!is.null(brush)) {
ranges[[paste('plot', i, 'x', sep = '')]] <- c(brush$xmin, brush$xmax)
ranges[[paste('plot', i, 'y', sep = '')]] <- c(brush$ymin, brush$ymax)
values[[paste('brushedPoints', i, sep = '')]] <- nrow(brushedPoints(mtcars[mtcars$cyl == 4], input[[paste('plot', i, '_brush', sep = '')]]))
}
})
})
observe({
lapply(1:input$n, function(i){
output[[paste0('Button', i)]] <- renderUI({
actionButton(inputId = paste0('button', i), label = 'x')
})
})
})
}
)