而无需更改标记大小

而无需更改标记大小

本文介绍了使用plotly proxy在plotly中更改迹线标记的颜色,而无需更改标记大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用plotlyproxy更改tracecolor,它可以正常工作,但是问题是,它还会改变我的标记/legendmarkers的大小.

I'm trying to use plotlyproxy to change the color of a trace, which works,but the problem is, is that it also alters the size of my markers / legendmarkers.

很久以前,我发现(据我目前的研究显示)仍然没有办法将图例标记的大小分别设置为与情节标记不同.

A long time ago I found out that there is (as far as my current research shows) still no way to separately set the size of legend markers to be different than the plot marker.

如果您想问我一个散布图或大图标记的结果,那么如果您想在散点图中绘制5000点,那将是一场灾难.

A disaster if you want to plot 5000 points in a scatter plot if you ask me as you end up with either tiny legends or giant plot markers.

所以问题是A或B解决方案类型:答:找到一种使用plotlyproxy而不更改我的legend marker size的方法或者B:找到一种方法来单独设置legend的大小,而plotlyproxy触发时不会受到影响

So the question is an A or B solution type:A: find a way to use plotlyproxy without changing my legend marker sizeorB: find a way to size the legend separately in a way that is not affected when plotlyproxy fires

我欢迎所有对图例大小问题有知识的人提供反馈.

I welcome any feedback from people who have knowledge on this legend size issue.

注意:可能可以使用javascript来完成,但是在这种情况下,我可能需要提供有关我正在使用的实际应用的更多信息,以使其正常工作

下面是要显示的虚拟应用程序:

here is the dummy app to show it:

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


ui <- fluidPage(
  fluidRow(
     column(8,
           plotlyOutput("plot1")
    ),
    column(2,
                   colourpicker::colourInput(inputId = 'markercolor', label = 'X',
           palette = "limited",
           showColour = "background", returnName = TRUE),
           selectInput(inputId = 'traceNo', label = 'Trace', choices = c(1:3), selected = 1),
           br(),
           h5('Switch'),
           actionButton(inputId = 'Switch', label = icon('refresh'), style = "color: #f7ad6e;   background-color: white;  border-color: #f7ad6e;
                        height: 40px; width: 40px; border-radius: 6px;  border-width: 2px; text-align: center;  line-height: 50%; padding: 0px; display:block; margin: 2px")
    )
  )
)

server <- function(input, output, session) {
  # values <- reactiveValues()


  observeEvent(input$Switch, {
    plotlyProxy("plot1", session) %>%
      plotlyProxyInvoke("restyle", list(marker = list(color = input$markercolor)), list(as.numeric(input$traceNo)-1))
    })

  output$plot1 <- renderPlotly({
    markersize <- 4
    markerlegendsize <- 20
   colors <- c('red', 'blue', 'black')
    p1 <- plot_ly()
    p1 <-  add_trace(p1, data = mtcars, x = ~disp, y = ~mpg, type = 'scatter', mode = 'markers', color = ~as.factor(cyl), colors = colors)
    p1 <- layout(p1, title = 'mtcars group by cyl with switching colors')
    p1 <- plotly_build(p1)

    ## this is a bit of a hack to change the size of the legend markers to not be equal to the plot marker size.
    ## it makes a list of 1 size value for each marker in de trace in the plot, and another half of with sizes that are a lot bigger.
    ## the legend marker size is effectively the average size of all markers of a trace
    for(i in seq(1, length(sort(unique(mtcars$cyl) )))) {
      length.group <- nrow(mtcars[which(mtcars$cyl  == sort(unique(mtcars$cyl))[i]), ])
      p1$x$data[[i]]$marker$size <- c(rep(markersize,length.group), rep(c(-markersize+2*markerlegendsize), length.group))
    }
    p1
  })
}

shinyApp(ui, server)

推荐答案

您可以使用ShinyJS注入custon javascript代码.在这里,我使用一些d3键选择图例项目并更改其大小.据我所知,它非常hacky,但不幸的是,plotly无法提供内部解决方案.

You can inject custon javascript code using shinyJS. Here, i use some d3 to select the legend items and change their size. It is very hacky but unfortunatly, as far as i know, plotly does not provide an internal solution.

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

jsCode <- "shinyjs.changelegend = function(){
var paths = d3.select('#plot1').
select('.legend').
select('.scrollbox').
selectAll('.traces').
select('.scatterpts')
.attr('d','M8,0A8,8 0 1,1 0,-8A8,8 0 0,1 8,0Z');}"

ui <- fluidPage(
  tags$script(src = "https://d3js.org/d3.v4.min.js"),
  useShinyjs(),
  extendShinyjs(text = jsCode),
  fluidRow(
    column(8,
           plotlyOutput("plot1")
    ),
    column(2,
           colourpicker::colourInput(inputId = 'markercolor', label = 'X',
                                     palette = "limited",
                                     showColour = "background", returnName = TRUE),
           selectInput(inputId = 'traceNo', label = 'Trace', choices = c(1:3), selected = 1),
           br(),
           h5('Switch'),
           actionButton(inputId = 'Switch', label = icon('refresh'), style = "color: #f7ad6e;   background-color: white;  border-color: #f7ad6e;
                        height: 40px; width: 40px; border-radius: 6px;  border-width: 2px; text-align: center;  line-height: 50%; padding: 0px; display:block; margin: 2px")
           )
    ),
  tags$div(id = "test")
  )

server <- function(input, output, session) {
  # values <- reactiveValues()


  observeEvent(input$Switch, {
    plotlyProxy("plot1", session) %>%
      plotlyProxyInvoke("restyle", list(marker = list(color = input$markercolor)), list(as.numeric(input$traceNo)-1))
  })

  observeEvent(input$Switch,{
    js$changelegend()
  })

  output$plot1 <- renderPlotly({
    markersize <- 4
    markerlegendsize <- 20
    colors <- c('red', 'blue', 'black')
    p1 <- plot_ly()
    p1 <-  add_trace(p1, data = mtcars, x = ~disp, y = ~mpg, type = 'scatter', mode = 'markers', color = ~as.factor(cyl), colors = colors)
    p1 <- layout(p1, title = 'mtcars group by cyl with switching colors')
    p1 <- plotly_build(p1)

    # this is a bit of a hack to change the size of the legend markers to not be equal to the plot marker size.
    # it makes a list of 1 size value for each marker in de trace in the plot, and another half of with sizes that are a lot bigger.
    # the legend marker size is effectively the average size of all markers of a trace
    for(i in seq(1, length(sort(unique(mtcars$cyl) )))) {
      length.group <- nrow(mtcars[which(mtcars$cyl  == sort(unique(mtcars$cyl))[i]), ])
      p1$x$data[[i]]$marker$size <- c(rep(markersize,length.group), rep(c(-markersize+2*markerlegendsize), length.group))
    }
    return(p1)
  })

}

shinyApp(ui, server)

自定义javascript代码在jsCode中定义,并在extendShinyjs()中初始化.最后,只要单击该按钮,就会在js$changelegend()中调用它.

The custom javascript code is defined in jsCode which is initialized in extendShinyjs(). Finally, it is invoked in js$changelegend() whenever the button is clicked.

如果有多个图并且希望具有相同的行为,则可以将图ID作为参数传递到js$changelegend()中,并相应地更改jsCode来进行处理.

If you have multiple plots and you want the same behavior, you can pass the plot id as a parameter into js$changelegend() and change the jsCode accordingly to handle this.

这篇关于使用plotly proxy在plotly中更改迹线标记的颜色,而无需更改标记大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-30 05:10