这希望是我对这个情节的最后一个问题。我之前收到过两次帮助,两次都在独立的绘图中工作,但我的绘图对象出现在一个闪亮的应用程序的上下文中提出了其他问题。
Kat 提出了两种解决方案:这里。
希望找到适合我的用例的解决方案,但需要自定义事件处理程序所需的 JavaScript 帮助来替换我当前拥有的“悬停时按颜色比较”的函数
{hovermode = 'x'}
。
本质上,我希望将按颜色悬停功能作为新的自定义模式栏按钮的选项。
数据:
library(shiny)
library(tidyverse)
library(plotly)
library(bslib)
library(htmlwidgets)
dat <- data.frame(group1=(rep(letters[1:4], each=5)),
group2=rep(LETTERS[1:5], times=4),
pct = c(rep(.2, times=5),
c(.1, .1, .1, .3, .4),
c(.2, .2, .2, .3, .1),
c(.3, .1, .2, .2, .2))
)
创建自定义按钮:
closest <- list(
name = "Show closest data on hover",
icon = list(
width = 1792,
height = 1792,
path = "M1203 544q0 13-10 23l-393 393 393 393q10 10 10 23t-10 23l-50 50q-10 10-23 10t-23-10l-466-466q-10-10-10-23t10-23l466-466q10-10 23-10t23 10l50 50q10 10 10 23z",
transform = 'matrix(1 0 0 -1 0 1792)'
),
click = htmlwidgets::JS(
"function(gd) {
Plotly.relayout(gd, {hovermode: 'closest'});
}"
)
)
colorcompare <- list(
name = "Compare by color on hover",
icon = list(
width = 1792,
height = 1792,
path = "M1011 1376q0 13-10 23l-50 50q-10 10-23 10t-23-10l-466-466q-10-10-10-23t10-23l466-466q10-10 23-10t23 10l50 50q10 10 10 23t-10 23l-393 393 393 393q10 10 10 23zm384 0q0 13-10 23l-50 50q-10 10-23 10t-23-10l-466-466q-10-10-10-23t10-23l466-466q10-10 23-10t23 10l50 50q10 10 10 23t-10 23l-393 393 393 393q10 10 10 23z",
transform = 'matrix(1 0 0 -1 0 1792)'
),
click = htmlwidgets::JS(
"function(gd) {
Plotly.relayout(gd, {hovermode: 'x'});
}"
)
)
ycompare <- list(
name = "Compare y data on hover",
icon = list(
width = 1792,
height = 1792,
path = "M1395 864q0 13-10 23l-466 466q-10 10-23 10t-23-10l-466-466q-10-10-10-23t10-23l50-50q10-10 23-10t23 10l393 393 393-393q10-10 23-10t23 10l50 50q10 10 10 23zm0-384q0 13-10 23l-466 466q-10 10-23 10t-23-10l-466-466q-10-10-10-23t10-23l50-50q10-10 23-10t23 10l393 393 393-393q10-10 23-10t23 10l50 50q10 10 10 23z",
transform = 'matrix(1 0 0 -1 0 1792)'
),
click = htmlwidgets::JS(
"function(gd) {
Plotly.relayout(gd, {hovermode: 'y'});
}"
)
)
最后,剧情:
plot <- dat %>%
plot_ly() %>%
add_bars(x = ~pct, y = ~group1, color = ~group2,
split = ~group2, customdata = ~group2,
hovertemplate = paste0("%{x:.2f%}<br>", "<extra>%{customdata}</extra>")) %>%
layout(yaxis = list(title = 'Group 1', autorange = 'reversed', categoryorder = 'trace'),
xaxis = list(title = 'Percent', tickformat = ".0%"),
barmode = 'stack', hovermode = 'y', legend = list(traceorder = "normal")) %>%
config(displaylogo = FALSE, modeBarButtonsToAdd = list(closest, colorcompare, ycompare),
modeBarButtonsToRemove = list('hoverCompareCartesian','hoverClosestCartesian'))
plot
我不确定这会如何影响你的 Shiny 应用程序中的其他内容 - 但是,如果没有 Shiny,这将起作用。
这会向主体添加一个类名称,然后每当您悬停时都会检查该类是否指示需要按颜色进行比较。
点击功能
closest
:
click = htmlwidgets::JS(
"function(gd) {
document.querySelector('body').classList.replace('byColor', 'no');
Plotly.relayout(gd, {hovermode: 'closest'});
}"
)
colorcompare
:
click = htmlwidgets::JS(
"function(gd) {
document.querySelector('body').classList.replace('no', 'byColor');
Plotly.relayout(gd, {hovermode: 'closest'});
}"
)
和
ycompare
:
click = htmlwidgets::JS(
"function(gd) {
document.querySelector('body').classList.replace('byColor', 'no');
Plotly.relayout(gd, {hovermode: 'y'});
}"
)
最后获取需要与您的绘图相匹配的
colorcompare
悬停和 onRender
调用的数据:
onRender(
"function(el, x) {
document.querySelector('body').classList.add('no');
el.on('plotly_hover', function(d) {
if(document.querySelector('body').classList.contains('byColor')) {
tellMe = d.points[0].pointNumber; /* changes by color */
gimme = d.points[0].curveNumber; /* stays the same by color */
let xlen = el.data[0].x.length; /* number of stacked bars */
let thatsIt = [];
for(i = 0; i < xlen; i++) { /* make a hover for each bar */
thatsIt.push({curveNumber: gimme, pointNumber: i})
}
Plotly.Fx.hover(el.id, thatsIt);
}
});
}")