javascript - 在不更改标记大小的情况下使用绘图代理更改跟踪标记的颜色
问题描述
我正在尝试使用plotlyproxy
来更改color
a trace
,这可行,但问题是,它也会改变我的标记 / 的大小legendmarkers
。
很久以前,我发现(据我目前的研究显示)仍然无法单独将图例标记的大小设置为与绘图标记不同。
如果你问我,如果你想在散点图中绘制 5000 个点,那将是一场灾难,因为你最终会得到微小的传说或巨大的情节标记。
所以问题是 A 或 B 解决方案类型: A:找到一种在plotlyproxy
不更改 mylegend
marker
size
或 B 的情况下使用的方法:找到一种方法以在火灾legend
时不受影响的方式单独调整大小plotlyproxy
我欢迎了解此图例大小问题的人提供任何反馈。
注意:可能这可以用 javascript 完成,但如果在这种情况下,我可能需要提供有关我正在开发的实际应用程序的更多信息才能使其正常工作
这是显示它的虚拟应用程序:
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 注入自定义 JavaScript 代码。在这里,我使用一些 d3 来选择图例项并更改它们的大小。这是非常 hacky 但不幸的是,据我所知,plotly 不提供内部解决方案。
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()
每当单击按钮时都会调用它。
如果您有多个绘图并且想要相同的行为,则可以将绘图 id 作为参数传递给js$changelegend()
并相应地更改jsCode
以处理此问题。
推荐阅读
- typescript - 如何将全局或外部函数调用到子函数中?
- java - 使用依赖反编译
- wso2 - WSO2 企业集成器入门
- node.js - node.js 的谷歌搜索模块不起作用?
- c++ - 如何将一个功能相乘/除以另一个功能?如何使用参数?
- python - 有没有办法让 Python 请求接受 HTTP 302 重定向并包含在初始响应中收到的 cookie?
- terminal - bash_profile 电力线设置
- google-sheets - 如何使用 4 个标准进行索引和匹配
- go - 在 Kubernetes 源代码中获取 Pod 的当前节点
- html - 如何在表格中居中特定项目?