如何为 R 闪亮的 App 旋转 3D Plotly 连续 [英] How to rotate 3D Plotly continuous for R shiny App

查看:12
本文介绍了如何为 R 闪亮的 App 旋转 3D Plotly 连续的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

I am trying to create a constant rotating 3D scatter plotly so that I can put it in my R shiny app. However, I can't seem to get it to constantly rotate (like this: https://codepen.io/etpinard/pen/mBVVyE). I don't want to save it to an image/gif just directly use in my App. Can anyone provide any help to get it continuously rotating (I have little experience with Python)? I've tried this in the Viewer screen of R studio, but it doesn't rotate there.

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
  
}

I am very new to plotly, so any help would be greatly appreciated.

解决方案

We can reuse most of the JS code via htmlwidgets::onRender. You tagged the question - wrapped it in an app accordingly:

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)


The same can be done via plotlyProxy without additional JS - but it's not as smooth:

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)

这篇关于如何为 R 闪亮的 App 旋转 3D Plotly 连续的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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