Home > Blockchain >  How to rotate 3D Plotly in R, update?
How to rotate 3D Plotly in R, update?

Time:11-25

I want to make an animated plot with a 3D surface

I was trying to replicate this example

Chrome error

This is the second code (without shiny)

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

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)

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.plot(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
      };
    }
  };
}
    ")

Im missing something on onRender?


Update: Thanks to @ismirsehregal for the update in the change of Plotly.plot to Plotly.update You can check the accepted answer

In case you need the version without Shiny, you can use this code

library(plotly)
library(htmlwidgets)

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)

PLT <- 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 / 1000);
      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
      };
    }
  };
}
    ")

PLT

CodePudding user response:

R plotly 4.10.0 recently updated the underlying plotly.js library from v1.57.1 to v2.5.1. This includes many breaking changes - With version 2.0 of plotly.js the function Plotly.plot was dropped.

To get back the old behaviour Plotly.plot can be replaced by Plotly.update:

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)
  • Related