Interactively adding points to plotly R without redrawing background plot

烂漫一生 提交于 2020-01-01 19:22:05

问题


The MWE below oversimplifies my real goal. However, I have a background image that takes a long time to draw (in the example below it is simply a scatterplot of 32 mtcars dataset values). Users can click on certain points from my background image, and this will cause new points to be plotted. My aim is for these new points to simply be redrawn on the top layer, while the background image scatterplot does not need to be redrawn to save time and computation.

My MWE is as follows:

library(plotly)
library(htmlwidgets)

g <- ggplot(mtcars, aes(x=mpg, y=cyl)) + geom_point()
gP <- ggplotly(g)

gP %>% onRender("
          function(el, x) {
            myGraph = document.getElementById(el.id);

            el.on('plotly_click', function(e) {

              console.log(e)
              console.log(e.points[0].x)

              var trace1 = {
                x: [e.points[0].x-.3, e.points[0].x-.3, e.points[0].x+.3, e.points[0].x+.3],
                y: [e.points[0].y-.3, e.points[0].y+.3, e.points[0].y-.3, e.points[0].y+.3],
                type: 'scatter',
                fillColor : 'red', 
                size: 20
              };

              Plotly.addTraces(el.id, trace1);
           })}
           ")

When a user clicks on any of the 32 black points, four colored red points are drawn around the clicked black point. This is mostly working, and if you click on any of the 32 black data points, you should see the four colored points drawn around it. However, I am left struggling with a few questions:

1) How can I improve this so that the four colored points are not connected by lines?

2) How can I make the size and fillColor actually work? When I change their values, I do not see them have an effect.

3) Is this a reasonable syntax to make the interactivity and drawing as fast as possible? I am pretty sure the background image is not being redrawn in an efficient manner but would love to hear confirmation about it as I am new to this syntax. If I were to add 100s of new points on the top layer, would this still be efficient? If not, I would be grateful to hear advice for recommendations for improved syntax.

Thank you.


回答1:


1) How can I improve this so that the four colored points are not connected by lines?

Add mode: 'markers' to your trace object

2) How can I make the size and fillColor actually work? When I change their values, I do not see them have an effect.

The values need to be inside the marker object and fillColor needs to be color.

marker: 
{
    color: 'red',   
    size: 20        
}

3) Is this a reasonable syntax to make the interactivity and drawing as fast as possible? I am pretty sure the background image is not being redrawn in an efficient manner but would love to hear confirmation about it as I am new to this syntax. If I were to add 100s of new points on the top layer, would this still be efficient? If not, I would be grateful to hear advice for recommendations for improved syntax.

That's a bit opinion based. The problem is that you use ggplot to create the template which creates quite a complicated plot. With 100 points you get quite some delay after each click.

Fixing the x/y-axis ranges will improve the drawing a bit because the graph does the need to be resized if the new values are outside the range of the old ones.

gP %>% 
  layout(
    xaxis = list(range = c(8, 35)),
    yaxis = list(range = c(3, 9))
  )

If you can draw the plot without using ggplotly you could create the trace only once and then append the values via extendTraces.

But I think it is as good as it can get, at the end it is a browser based library and not a standalone program.


library(plotly)
library(htmlwidgets)

g <- ggplot(mtcars, aes(x=mpg, y=cyl)) + geom_point()
gP <- ggplotly(g)
gP %>% 
 layout(
    xaxis = list(range = c(8, 35)),
    yaxis = list(range = c(3, 9))
  )

gP %>% onRender("
function(el, x) {
  myGraph = document.getElementById(el.id);
  el.on('plotly_click', function(e) 
    {

      var trace1 = {
        x: [],
        y: [],
        mode: 'markers',
        marker: {
          color: 'red',   
          size: 20
        }
      };
      for (var i = 0; i < 100; i+= 1){
        trace1.x.push(e.points[0].x + Math.random() - 0.5)
        trace1.y.push(e.points[0].y + Math.random() - 0.5)
      }
    Plotly.addTraces(el.id, trace1);
  }
)}
")


来源:https://stackoverflow.com/questions/42382973/interactively-adding-points-to-plotly-r-without-redrawing-background-plot

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!