Joe Healey Joe Healey - 3 months ago 45
R Question

create a video from plotly 3d chart

I'm wondering if anyone knows of a way to export plotly 3d charts as a video (more specifically if this can be done natively or requires bodging)?

Exporting a static image is simple, and exporting the interactive plots is fine for embedding in HTML etc.

Lets say I have a 3D chart that I want so simply rotate slowly, this seems like it could be pretty straight forward if the image can be rotated a given interval, an image taken, rotated further ad infinitum, perhaps in a loop - but I'm wondering if this isn't somehow supported natively?

Anyone know of a good strategy?

Solution ideally for R/RStudio, but since plotly is cross-platform, any solutions considered.

Answer

This is a somewhat partial answer for future reference:

The key to being able to iterate multiple perspectives turns out to lie in the camera control "eye", the plotly help centre pointed me toward this:

https://plot.ly/r/reference/#layout-scene-camera

camera = list(eye = list(x = 1.25, y = 1.25, z = 1.25))) #1.25 is default

This is kind of answered here, though searching for my specific query as above didn't find it:

http://stackoverflow.com/questions/34178381/how-to-specify-camera-perspective-of-3d-plotly-chart-in-r

I haven't yet implemented this fully as I've not had the time, but wrapping the plot function in a loop which passes sequential values to the eye command, and renders each one should produce a stack of images which can then be 'concatenated' in to frames for a gif/video in your media creator of choice.

This is code I just threw together in this answer so isn't tested - treat as pseudocode would be my advice...

# assume dataset read in, manipulated and given as a matrix in "matrix"
matrix.list <- list(
                x = temp,
                y = scan,
                z = matrix
                )
font.pref <- list(size=12,family="Arial, sans-serif",color="black")
x.list <- list(title = "Temperature (˚C)",titlefont = font.pref)
y.list <- list(title = "Wavelength (nm)",titlefont = font.pref)
z.list <- list(title = "CD Intensity",titlefont = font.pref)

for(i in seq(0,4,by=0.1){
outfile <- paste(file,"plot",i, sep = "_")

graph <- plot_ly(matrix.list,x = temp,y = scan,z = z,
                 type="surface",
                 colors=c("black","grey","red"),
                 colorbar = list(title="CD Intensity")) %>%
                  layout(scene=list(xaxis = x.list,
                                    yaxis = y.list,
                                    zaxis = z.list,
                                    camera = list(eye = list(x = cos(i), y = sin(i), z= 0.25)))) # Should orbit horizontally around the chart
graph

plotly_IMAGE(graph,
             width = 1600,
             height = 1400,
             format = "png",
             username="xxx",
             key="xxx",
             scale = 1,
             out_file = paste(outfile,"png", sep="."))
}

NB As I say, I've not yet tried this, and with the above image parameters you'd end up with a lot of images that might be pretty large.