[英]R: How to modify the legend in plotly?
I have 3 numerical variables and plotting them via barchart in plot_ly
.我有 3 个数值变量并通过plot_ly
中的条形图绘制它们。 'sale' and 'share' columns are visualized via bars, while 'cost' by red line. “销售”和“分享”列通过条形显示,而“成本”则通过红线显示。 Now I want to customize legend a bit and add black border around cost in legend map (see expected outcome)现在我想稍微自定义一下图例并在图例地图中的成本周围添加黑色边框(见预期结果)
df <- data.frame (model = c("A", "B", "C","D","E","F"),
share = c(12,20,15,9,60,20),
sale = c(16,25,18,14,67,28),
cost = c(14,19,28,24,57,28))
#set levels of model by cost
df$model <- factor(df$model, levels = arrange(df, desc(df$cost))$model)
library(tidyverse)
df_long <- df %>%
pivot_longer(
cols = -model
)
df_long %>%
filter(name != "cost") %>%
plot_ly(x = ~model, y = ~value, color = ~name, type = "bar",
customdata = ~name, colors = c("blue", "gray"),
hovertemplate = paste0("Model: %{x}<br>Value: %{y}<br>",
"Name: %{customdata}<extra></extra>")) %>%
add_lines(inherit = F, data = df, x = ~model,
y = ~cost, color = I("red"),
name = "cost",
hovertemplate = paste0("Model: %{x}<br>Value: %{y}<br>",
"Name: cost<extra></extra>")) %>%
add_annotations(data = df, x = ~model, y = ~cost, text = ~cost,
bgcolor = "white", bordercolor = "black",
xshift = 15, yshift = 15, showarrow = F) %>%
layout(barmode = "group")
output:输出:
This one was tricky!这个很棘手! I know that Plotly doesn't have anything built-in to do this simply.我知道 Plotly 没有任何内置功能可以简单地做到这一点。 I tried to work out using shapes to draw this box, but that doesn't work, because it puts the legend on top (so most of the box is hidden).我尝试使用形状来绘制这个框,但这不起作用,因为它将图例放在顶部(所以大部分框都被隐藏了)。 I'm apparently more stubborn than Plotly though.不过,我显然比 Plotly 更固执。
This answer requires the package htmlwidgets
.这个答案需要包htmlwidgets
。 I didn't change your plot other an assigning it to an object.我没有改变你的情节,把它分配给一个对象。 I named your Plotly object pL
for this answer.我将此答案命名为您的 Plotly 对象pL
。
The content for the onRender
function: onRender
函数的内容:
or = ("function(el){
costLeg = document.querySelectorAll('g.traces')[2]; /* third legend entry */
cChW = costLeg.firstChild.getBoundingClientRect().width; /* text only */
cR = costLeg.lastChild.getBoundingClientRect(); /*g trace space*/
cR2 = costLeg.lastChild.outerHTML.split('\" ');
cy = cR2[3].split('\"')[1]; /* the y without padding*/
cDf = cR.width - cChW - 14; /*legend width - text width - padding*/
costLC = costLeg.lastChild.cloneNode(true); /* copy the current rect element */
costLC.removeAttribute('pointer-events'); /* remove the pointer events */
costLeg.removeAttribute('class'); /*stop refresh from changing it*/
costLC.setAttribute('x', 3); /* calc values + or minus padding */
costLC.setAttribute('y', (cR.height - 6)/2 * -1); /* measure from center */
costLC.setAttribute('width', cDf);
costLC.setAttribute('height', cR.height - 6);
costLC.setAttribute('style',
'fill: rgb(0, 0, 0); fill-opacity: 0; stroke-width: 2px; stroke: black;');
costLeg.insertBefore(costLC, costLeg.lastChild);
}")
Call the plot and add the onRender
function to draw the box.调用绘图并添加onRender
函数以绘制框。
pL %>% htmlwidgets::onRender(or)
By the way, this should scale with your plot, as well.顺便说一句,这也应该与你的情节相适应。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.