R在服务器中构建colorInput时,使用javascript更新跟踪颜色

R在服务器中构建colorInput时,使用javascript更新跟踪颜色,javascript,r,shiny,plotly,r-plotly,Javascript,R,Shiny,Plotly,R Plotly,这是对上一个问题的修改版本 在该应用程序中(更好地反映了我的真实应用程序),会发生以下情况: 我有两套绘图, -一组的两个绘图显示相同的轨迹,只是绘制了不同的列 -在我的应用程序中,每个绘图都位于不同的页面上 -两个绘图应链接到第2页的一组颜色输入 -colorInputs内置于带有renderUI*1的服务器中 *1:出于这个原因,我认为,p%>%onRender(js)方法不会像我在前面讨论的YNbuttons中看到的那样起作用 目标: 如果colorInput'COL\u按钮\u plot

这是对上一个问题的修改版本

在该应用程序中(更好地反映了我的真实应用程序),会发生以下情况:

我有两套绘图,
-一组的两个绘图显示相同的轨迹,只是绘制了不同的列
-在我的应用程序中,每个绘图都位于不同的页面上
-两个绘图应链接到第2页的一组
颜色输入

-
colorInputs
内置于带有
renderUI
*1的服务器中

*1:出于这个原因,我认为,
p%>%onRender(js)
方法不会像我在前面讨论的
YNbuttons
中看到的那样起作用

目标: 如果
colorInput
'COL\u按钮\u plot1\u plot2\u N'
更改->更改
绘图1
绘图2
跟踪
N-1
(*2)的
颜色

*2:跟踪编号为
0-n,
因此
colorInput nr-1

我修改了colorInputs的命名代码,以包含它们应该针对的两个绘图的名称:

COLElement_1 <-    function(idx){sprintf("COL_button_plot1_plot2_%d",idx)}
测试应用程序:

   library(plotly)
    library(shiny)
    library(colourpicker)
    library(htmlwidgets)

# jscolor <- c(......)

ui <- fluidPage(
  tags$head(
    tags$script(HTML(jscolor))  ## to add the javascript to the app
  ),
  fluidRow(
    column(4,plotlyOutput("plot1")),
    column(4,plotlyOutput("plot2")),
    column(4,uiOutput('buttons_color_1')
    )
  ),
  fluidRow(
    column(4,plotlyOutput("plot3")),
    column(4,plotlyOutput("plot4")),
    column(4,uiOutput('buttons_color_2'))
)
)

server <- function(input, output, session) {
   #functions to make colorinput IDs
  COLElement_1 <-    function(idx){sprintf("COL_button_plot1_plot2_%d",idx)}
  COLElement_2 <-    function(idx){sprintf("COL_button_plot3_plot4_%d",idx)}

  TheColors <- c('#383838', '#5b195b','#1A237E', '#000080', '#224D17', '#cccc00', '#b37400',  '#990000', 
                 '#505050',  '#a02ca0',  '#000099', '#2645e0', '#099441', '#e5e500', '#cc8400', '#cc0000', 
                 '#737373', '#e53fe5', '#0000FF', '#4479e1',  '#60A830', '#ffff00','#e69500', '#ff0000', 
                 '#b2b2b2', '#eb6ceb', '#6666ff', '#d0a3ff', '#9FDA40',  '#ffff7f', '#ffa500', '#ff4c4c',
                 '#d9d9d9',  '#f198f1',  '#C5CAE9','#BBDEFB','#D9DF1D', '#ffffcc','#ffc04d', '#ff9999')

  values <- reactiveValues(colors1 = TheColors, colors2 = sort(TheColors))
  lapply(c(1:2), function(i) {
    output[[paste('buttons_color_', i,sep = '')]] <- renderUI({
      isolate({ lapply(1:3, function(x) {  ## 3 in my app changes based on clustering output of my model
        Idname <- if(i == 1) { COLElement_1(x) } else {COLElement_2(x) }
        div(colourpicker::colourInput(inputId = Idname, label = NULL,
                                      palette = "limited", allowedCols = TheColors,
                                      value = values[[paste('colors', i, sep = '')]][x],
                                      showColour = "background", returnName = TRUE),
            style = " height: 30px; width: 30px; border-radius: 6px;  border-width: 2px; text-align:center; padding: 0px; display:block; margin: 10px",
            onclick = "toggleColor(this.id)")
      })
      })})

    outputOptions(output, paste('buttons_color_', i,sep = ''), suspendWhenHidden=FALSE)
  })



  myplotly <- function(THEPLOT, xvar, setnr) {
    markersize <- input[[paste('markersize', THEPLOT, sep = '_')]]
    markerlegendsize <- input[[paste('legendsize', THEPLOT, sep = '_')]]
    colors <- isolate ({values[[paste('colors', setnr, sep = '')]]  })
    p <- plot_ly(source = paste('plotlyplot', THEPLOT, sep = '.'))
    p <-  add_trace(p, data = mtcars, x = mtcars[[xvar]], y = ~mpg, type = 'scatter', mode = 'markers', color = ~as.factor(cyl), colors = colors)
    p <- layout(p, title = 'mtcars group by cyl with switching colors')
    p <- plotly_build(p)
    p 
  }

  output$plot1 <- renderPlotly({ myplotly('plot1', 'hp', 1) })
  output$plot2 <- renderPlotly({ myplotly('plot2', 'disp', 1)})
  output$plot3 <- renderPlotly({ myplotly('plot3','hp', 2)})
  output$plot4 <- renderPlotly({ myplotly('plot4', 'disp', 2)})

}

shinyApp(ui, server)
library(plotly)
图书馆(闪亮)
图书馆(色彩采集器)
库(htmlwidgets)

#jscolor您的JS代码中有一些输入错误,
此.value
不返回颜色选择器的值

jscolor <- c(
  "function toggleColor(id){",
  "  var color = document.getElementById(id).value;", # get the color of the colourpicker
  "  var ids = id.split('_');", # split the ids
  "  var plotAid = ids[2];", #get the id of plotA (plot1 or 3)
  "  var plotBid = ids[3];", #get the id of plotB (plot2 or 4)
  "  var index = parseInt(ids[4]) -1;", #get the trace number to target
  "  var plotA = document.getElementById(plotAid);", #get the plot element
  "  var dataA = plotA.data;", #access the plot data
  "  var markerA = dataA[index].marker;", #access the plot's markers
  "  markerA.color = color;",  # set the marker color
  "  Plotly.restyle(plotA, {marker: markerA}, [index]);", #restyle plotA
  "  var plotB = document.getElementById(plotBid);", # repeat steps for plot2
  "  var dataB = plotB.data;",
  "  var markerB = dataB[index].marker;",
  "  markerB.color = color;",
  "  Plotly.restyle(plotB, {marker: markerB}, [index]);",
  "};"
)
server.R
中:

  lapply(c(1:2), function(i) {
    output[[paste('buttons_color_', i,sep = '')]] <- renderUI({
      inputs <- lapply(1:3, function(x) {  ## 3 in my app changes based on clustering output of my model
        Idname <- if(i == 1) { COLElement_1(x) } else {COLElement_2(x) }
        colour_input <- colourInput2(inputId = Idname, label = NULL,
                                     palette = "limited", allowedCols = TheColors,
                                     value = isolate(values[[paste('colors', i, sep = '')]][x]),
                                     showColour = "background", returnName = FALSE, 
                                     onchange = "toggleColor(this.id)")
        div(colour_input,
            style = "height: 30px; width: 30px; border-radius: 6px;  border-width: 2px; text-align:center; padding: 0px; display:block; margin: 10px"
        )
      })
      do.call(tagList, inputs)
    })
    # useless: outputOptions(output, paste('buttons_color_', i,sep = ''), suspendWhenHidden=FALSE)
  })
lappy(c(1:2),函数(i){

输出[[粘贴('buttons\u color\u',i,sep='')]事实上,我很惊讶我离正确的javascript如此之近。看来我至少从你的帮助中学到了一些东西Stephane!当我将此解决方案与按钮图例链接javascript结合使用时,遇到了一些奇怪的问题。明天将继续看我是否能够找出错误,尝试通过修改工作找出错误我发现第一个障碍似乎是绘图名称。在更新后的应用程序中,我将其中一个绘图的名称从plot1替换为plotx,突然绘图不再工作,即使其名称的所有引用都已更改。你能找出我缺少Stephane的原因吗?Stépahne,知道吗你知道为什么不同的情节名称不起作用吗?我很抱歉stuck@Mark不知道抱歉,这很奇怪,没有理由不使用其他名称。
jscolor <- c(
  "function toggleColor(id){",
  "  var color = document.getElementById(id).value;", # get the color of the colourpicker
  "  var ids = id.split('_');", # split the ids
  "  var plotAid = ids[2];", #get the id of plotA (plot1 or 3)
  "  var plotBid = ids[3];", #get the id of plotB (plot2 or 4)
  "  var index = parseInt(ids[4]) -1;", #get the trace number to target
  "  var plotA = document.getElementById(plotAid);", #get the plot element
  "  var dataA = plotA.data;", #access the plot data
  "  var markerA = dataA[index].marker;", #access the plot's markers
  "  markerA.color = color;",  # set the marker color
  "  Plotly.restyle(plotA, {marker: markerA}, [index]);", #restyle plotA
  "  var plotB = document.getElementById(plotBid);", # repeat steps for plot2
  "  var dataB = plotB.data;",
  "  var markerB = dataB[index].marker;",
  "  markerB.color = color;",
  "  Plotly.restyle(plotB, {marker: markerB}, [index]);",
  "};"
)
colourInput2 <- function(inputId, label, value = "white", 
                         showColour = c("both", "text", "background"), 
                         palette = c("square", "limited"), allowedCols = NULL,
                         allowTransparent = FALSE, returnName = FALSE, 
                         onchange){
  input <- colourInput(inputId, label, value, showColour, palette, 
                       allowedCols, allowTransparent, returnName)
  attribs <- c(input$children[[2]]$attribs, onchange = onchange)
  input$children[[2]]$attribs <- attribs
  input
}
  lapply(c(1:2), function(i) {
    output[[paste('buttons_color_', i,sep = '')]] <- renderUI({
      inputs <- lapply(1:3, function(x) {  ## 3 in my app changes based on clustering output of my model
        Idname <- if(i == 1) { COLElement_1(x) } else {COLElement_2(x) }
        colour_input <- colourInput2(inputId = Idname, label = NULL,
                                     palette = "limited", allowedCols = TheColors,
                                     value = isolate(values[[paste('colors', i, sep = '')]][x]),
                                     showColour = "background", returnName = FALSE, 
                                     onchange = "toggleColor(this.id)")
        div(colour_input,
            style = "height: 30px; width: 30px; border-radius: 6px;  border-width: 2px; text-align:center; padding: 0px; display:block; margin: 10px"
        )
      })
      do.call(tagList, inputs)
    })
    # useless: outputOptions(output, paste('buttons_color_', i,sep = ''), suspendWhenHidden=FALSE)
  })