r - 如何为 R shiny App 连续旋转 3D Plotly

标签 r animation shiny plotly r-plotly

我正在尝试创建一个恒定旋转的 3D 散点图,以便我可以将它放入我的 R Shiny 应用程序中。但是,我似乎无法让它不断旋转(像这样:https://codepen.io/etpinard/pen/mBVVyE)。 我不想将它保存到直接在我的应用程序中使用的图像/gif。谁能提供任何帮助让它不断旋转(我对 Python 的经验很少)?我已经在 R studio 的查看器屏幕中尝试过,但它不会在那里旋转。

library(plotly)
library(ggplot2)


N <- 100

x <- rnorm(N, mean = 50, sd = 2.3)
y <- runif(N,min= 0, max = 100)
z <- runif(N, min = 4, max = 70)
luci.frame <- data.frame(x,y,z)




for (i in seq(0,100, by=0.1)){
  cam.zoom = 2
  ver.angle = 0
  graph <- plot_ly()%>%
    add_trace(type = "scatter3d", 
              mode = "markers", 
              data = luci.frame,
              x = ~x, 
              y = ~y, 
              z = ~z) %>%
    layout(scene = list(
      camera = list(
        eye = list(
          x = cos(i)*cam.zoom,
          y = sin(i)*cam.zoom, 
          z = 0.3
        ), 
        center = list(
          x = 0, 
          y = 0, 
          z = 0
        )
        
      )
      
      
    )
    )
  graph
  
}

我是 plotly 的新手,所以非常感谢任何帮助。

最佳答案

我们可以通过 htmlwidgets::onRender 重用大部分 JS 代码。您标记了问题 - 将其相应地包装在应用程序中:

library(shiny)
library(plotly)
library(htmlwidgets)

ui <- fluidPage(
  plotlyOutput("graph")
)

server <- function(input, output, session) {
  N <- 100
  x <- rnorm(N, mean = 50, sd = 2.3)
  y <- runif(N, min = 0, max = 100)
  z <- runif(N, min = 4, max = 70)
  luci.frame <- data.frame(x, y, z)
  
  output$graph <- renderPlotly({
    plot_ly(
      type = "scatter3d",
      mode = "markers",
      data = luci.frame,
      x = ~ x,
      y = ~ y,
      z = ~ z
    ) %>%
      layout(scene = list(camera = list(
        eye = list(
          x = 1.25,
          y = 1.25,
          z = 1.25
        ),
        center = list(x = 0,
                      y = 0,
                      z = 0)
      ))) %>%
      onRender("
      function(el, x){
  var id = el.getAttribute('id');
  var gd = document.getElementById(id);
  Plotly.update(id).then(attach);
  function attach() {
    var cnt = 0;
    
    function run() {
      rotate('scene', Math.PI / 180);
      requestAnimationFrame(run);
    } 
    run();
    
    function rotate(id, angle) {
      var eye0 = gd.layout[id].camera.eye
      var rtz = xyz2rtz(eye0);
      rtz.t += angle;
      
      var eye1 = rtz2xyz(rtz);
      Plotly.relayout(gd, id + '.camera.eye', eye1)
    }
    
    function xyz2rtz(xyz) {
      return {
        r: Math.sqrt(xyz.x * xyz.x + xyz.y * xyz.y),
        t: Math.atan2(xyz.y, xyz.x),
        z: xyz.z
      };
    }
    
    function rtz2xyz(rtz) {
      return {
        x: rtz.r * Math.cos(rtz.t),
        y: rtz.r * Math.sin(rtz.t),
        z: rtz.z
      };
    }
  };
}
    ")
  })
}

shinyApp(ui, server)

result1


同样可以通过 plotlyProxy 完成而无需额外的 JS - 但它并不那么流畅:

library(shiny)
library(plotly)

ui <- fluidPage(
  plotlyOutput("graph")
)

server <- function(input, output, session) {
  N <- 100
  x <- rnorm(N, mean = 50, sd = 2.3)
  y <- runif(N, min = 0, max = 100)
  z <- runif(N, min = 4, max = 70)
  luci.frame <- data.frame(x, y, z)
  
  mySequence <- seq(0, 100, by = 0.1)
  
  cam.zoom = 2
  # ver.angle = 0
  
  output$graph <- renderPlotly({
    plot_ly(
      type = "scatter3d",
      mode = "markers",
      data = luci.frame,
      x = ~ x,
      y = ~ y,
      z = ~ z
    ) %>%
      layout(scene = list(camera = list(
        eye = list(
          x = cos(mySequence[1]) * cam.zoom,
          y = sin(mySequence[1]) * cam.zoom,
          z = 0.3
        ),
        center = list(x = 0,
                      y = 0,
                      z = 0)
      )))
  })
  
  myPlotlyProxy <- plotlyProxy("graph")
  count <- reactiveVal(1L)
  
  observe({
    invalidateLater(100)
    plotlyProxyInvoke(myPlotlyProxy, "relayout", list(scene = list(camera = list(
      eye = list(
        x = cos(mySequence[isolate(count())]) * cam.zoom,
        y = sin(mySequence[isolate(count())]) * cam.zoom,
        z = 0.3
      ),
      center = list(x = 0,
                    y = 0,
                    z = 0)
    ))))
    
    isolate(count(count()+1))
    
    if(count() > length(mySequence)){
      count(1L)  
    }
  })
}

shinyApp(ui, server)

result2

关于r - 如何为 R shiny App 连续旋转 3D Plotly,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66110647/

相关文章:

r - rmarkdown 中的嵌套有序列表

css - SVG 和 CSS 重力动画

iphone - iOS 支持哪些动画文件类型?

javascript - 如何让 react-pose 与类组件一起工作?

rpivotTable:删除不必要的聚合器

r - 如何在Shiny中自动“调整大小” ggplot?

r - Shiny :无法在 Shiny 的数据表中设置列宽

string - 忽略 R 字符串中的转义字符(反斜杠)

r - 什么是命名号码?

r - 在 R 中向 igraph 添加文本