R语言中实现Plotly 3D图表自动旋转的方法及问题修复
3D曲面动画图表无法旋转问题排查与解决
问题说明
我想要制作3D曲面动画图表,尝试复现相关公开示例时,运行代码后图表无法旋转,RStudio控制台无报错信息。后续我编写了移除Shiny依赖的独立版本代码,用于直接导出为HTML文件,但在Chrome浏览器打开后,调试工具提示渲染错误。
初始测试代码
带Shiny依赖版本
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.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 }; } }; } ") }) } shinyApp(ui, server)
无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 }; } }; } ")
最初猜测问题出在onRender部分的代码存在缺失。
问题原因与解决方案
经排查,问题根源为当前Plotly版本的JS接口不兼容Plotly.plot调用,将其替换为Plotly.update即可解决无法旋转和渲染报错的问题,同时可将旋转步长调整为Math.PI / 1000获得更流畅的动画效果。
可用的无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) 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
内容的提问来源于stack exchange,提问作者ppriede
相关产品推荐
相关产品推荐

