问题描述
我正在尝试使用plotlyproxy
更改trace
的color
,它可以正常工作,但是问题是,它还会改变我的标记/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
size
orB: 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中更改迹线标记的颜色,而无需更改标记大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!