闪亮:如何更改点击点的形状和/或大小? [英] Shiny: How to change the shape and/or size of the clicked point?

查看:88
本文介绍了闪亮:如何更改点击点的形状和/或大小?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在下图中更改单击点的形状和大小.如何实现呢?对于这个玩具情节,我将积分的数量从原来的100k减少到了2k.因此,预期的解决方案应该具有高度的可扩展性,并且不要偏离原始图,即,单击点更新前后的所有颜色都应该相同.

I would like to change the shape and size of the clicked point in the below plot. How to achieve it? For this toy plot, I have reduced the number of points from original 100k to 2k. So, the expected solution should be highly scalable and do not deviate from the original plot i.e., all the colors before and after the update of the click point should be the same.

library(shiny)
library(plotly)

df <- data.frame(X=runif(2000,0,2), Y=runif(2000,0,20), 
                 Type=c(rep(c('Type1','Type2'),600),
                        rep(c('Type3','Type4'),400)),
                 Val=sample(LETTERS,2000,replace=TRUE))

# table(df$Type, df$Val)

ui <- fluidPage(
  title = 'Select experiment',
  sidebarLayout(
    sidebarPanel(
      checkboxGroupInput("SelType", "Select Types to plot:",
                  choices = unique(df$Type),
                  selected = NA)
    ),
    mainPanel(
      plotlyOutput("plot", width = "400px"),
      verbatimTextOutput("click")
    )
  )
)


server <- function(input, output, session) {

  output$plot <- renderPlotly({
    if(length(input$SelType) != 0){
      df <- subset(df, Type %in% input$SelType)
      p <- ggplot(df, aes(X, Y, col = as.factor(Val))) + 
        geom_point()
    }else{
      p <- ggplot(df, aes(X, Y, col = as.factor(Val))) +
        geom_point()
    }
    ggplotly(p)  %>% layout(height = 800, width = 800)

  })

  output$click <- renderPrint({
    d <- event_data("plotly_click")
    if (is.null(d)) "Click events appear here (double-click to clear)" 
    else cat("Selected point associated with value: ", d$Val)
  })

}

shinyApp(ui, server)

此处已经提出了一个相关的问题,但是用颜色突出显示该点的方法没有工作(当变量的级别数很高时,很难对图中可能已经存在的颜色进行硬编码).

A related question has been asked here, but that approach of highlighting the point with a color does not work(when the number of levels of a variable is high, it is difficult to hard code a color which might be already present in the plot).

推荐答案

Plotly的restyle函数在这里无济于事,但我们仍然可以使用onclick

Plotly's restyle function won't help us here but we can still use the onclick event together with a little bit of JavaScript. The code has acceptable performance for 10,000 points.

我们可以使用以下方法获得在JavaScript中单击的要点:

We can get the point which was clicked on in JavaScript using:

var point = document.getElementsByClassName('scatterlayer')[0].getElementsByClassName('scatter')[data.points[0].curveNumber].getElementsByClassName('point')[data.points[0].pointNumber];

(scatterlayer是所有散点图元素所在的层, scatter[n]是第n个散点图,point[p]是其中的第p个点)

(scatterlayer is the layer where all the scatterplot elements are located, scatter[n] is the n-th scatter plot and point[p] is the p-th point in it)

现在,我们将这一点扩大很多(或您想要的任何其他形状/变换):

Now we just make this point a lot bigger (or whatever other shape/transformation you want):

point.setAttribute('d', 'M10,0A10,10 0 1,1 0,-10A10,10 0 0,1 10,0Z');

为了获得还原所有内容的可能性,我们将有关该点的未更改信息与其余的Plotly信息一起存储:

In order to get the possibility to revert everything, we store the unaltered info about the point together with the rest of the Plotly information:

var plotly_div = document.getElementsByClassName('plotly')[0];
plotly_div.backup = {curveNumber: data.points[0].curveNumber,
                     pointNumber: data.points[0].pointNumber,
                     d: point.attributes['d'].value
                    }

然后我们可以恢复原点:

and later we can restore the point:

var old_point = document.getElementsByClassName('scatterlayer')[0].getElementsByClassName('scatter')[plotly_div.backup.curveNumber].getElementsByClassName('point')[plotly_div.backup.pointNumber]
old_point.setAttribute('d', plotly_div.backup.d);

现在,我们可以将所有代码添加到plotly小部件中.

Now we can add all the code to the plotly widget.

javascript <- "
function(el, x){
  el.on('plotly_click', function(data) {
    var point = document.getElementsByClassName('scatterlayer')[0].getElementsByClassName('scatter')[data.points[0].curveNumber].getElementsByClassName('point')[data.points[0].pointNumber];
    var plotly_div = document.getElementsByClassName('plotly')[0];
    if (plotly_div.backup !== undefined) {
      var old_point = document.getElementsByClassName('scatterlayer')[0].getElementsByClassName('scatter')[plotly_div.backup.curveNumber].getElementsByClassName('point')[plotly_div.backup.pointNumber]
      if (old_point !== undefined) {
        old_point.setAttribute('d', plotly_div.backup.d);
      }
    }
    plotly_div.backup = {curveNumber: data.points[0].curveNumber,
                         pointNumber: data.points[0].pointNumber,
                         d: point.attributes['d'].value,
                         style: point.attributes['style'].value
                        }

    point.setAttribute('d', 'M10,0A10,10 0 1,1 0,-10A10,10 0 0,1 10,0Z');
  });
}"

[...]

ggplotly(p) %>% onRender(javascript)


或者,您也可以根据点击点的位置制作新的SVG元素,但可以使用所需的颜色和形状.


Alternatively you could make a new SVG element based on the location of the clicked point but in the color and shape you would like.

您可以在没有R/Shiny的情况下在这里尝试.

You can try it here without R/Shiny.

//create some random data
var data = [];
for (var i = 0; i < 10; i += 1) {
  data.push({x: [],
             y: [],
             mode: 'markers',
             type: 'scatter'});
  for (var p = 0; p < 200; p += 1) {
    data[i].x.push(Math.random());
    data[i].y.push(Math.random());
  }
}
//create the plot
var myDiv = document.getElementById('myDiv');
Plotly.newPlot(myDiv, data, layout = { hovermode:'closest'});

//add the same click event as the snippet above
myDiv.on('plotly_click', function(data) {
    //let's check if some traces are hidden

    var traces = document.getElementsByClassName('legend')[0].getElementsByClassName('traces');
    var realCurveNumber = data.points[0].curveNumber;
    for (var i = 0; i < data.points[0].curveNumber; i += 1) {
        if (traces[i].style['opacity'] < 1) {
            realCurveNumber -= 1
        }
    }

    data.points[0].curveNumber = realCurveNumber;
    var point = document.getElementsByClassName('scatterlayer')[0].getElementsByClassName('scatter')[data.points[0].curveNumber].getElementsByClassName('point')[data.points[0].pointNumber];
    var plotly_div = document.getElementsByClassName('plotly')[0];
    if (plotly_div.backup !== undefined) {
      var old_point = document.getElementsByClassName('scatterlayer')[0].getElementsByClassName('scatter')[plotly_div.backup.curveNumber].getElementsByClassName('point')[plotly_div.backup.pointNumber]
      if (old_point !== undefined) {
        old_point.setAttribute('d', plotly_div.backup.d);
      }
    }
    plotly_div.backup = {curveNumber: data.points[0].curveNumber,
                         pointNumber: data.points[0].pointNumber,
                         d: point.attributes['d'].value,
                         style: point.attributes['style'].value
                        }

    point.setAttribute('d', 'M10,0A10,10 0 1,1 0,-10A10,10 0 0,1 10,0Z');
  });

<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id="myDiv">

这篇关于闪亮:如何更改点击点的形状和/或大小?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆