如何为 R 闪亮的 App 旋转 3D Plotly 连续 [英] How to rotate 3D Plotly continuous for R shiny App
问题描述
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 shiny - 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屋!