Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions docs/apps/TemplatePlotly/animated_js/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import numpy as np
import plotly.graph_objects as go
from shiny import App, Inputs, Outputs, Session, render, ui

app_ui = ui.page_sidebar(
ui.sidebar(
ui.input_slider("sigma", "Sigma (s)", min=0, max=20, value=10, step=0.1),
ui.input_slider("beta", "Beta (b)", min=0, max=5, value=8/3, step=0.01),
ui.input_slider("rho", "Rho (r)", min=0, max=50, value=28, step=0.5),
ui.input_slider("n", "Number of points", min=10, max=500, value=100, step=10),
ui.input_slider("dt", "Time step (dt)", min=0.001, max=0.05, value=0.015, step=0.001),
),
ui.output_ui("plot", height="100%")
)



def server(input: Inputs, output: Outputs, session: Session):

@render.ui
def plot():
s = input.sigma()
b = input.beta()
r = input.rho()
dt = input.dt()

n = input.n()

fig = go.Figure(
)

plot_html = fig.to_html(
auto_play=False,
include_plotlyjs=True,
full_html=False,
div_id="animated_plot"
)

loop_script = f"""
<script>
(function () {{
// ----- DESTROY PREVIOUS INSTANCE -----
if (window.lorenzAnimation) {{
cancelAnimationFrame(window.lorenzAnimation.frameId);
Plotly.purge('animated_plot');
window.lorenzAnimation = null;
}}

// ----- CREATE NEW INSTANCE -----
var controller = {{
frameId: null
}};
window.lorenzAnimation = controller;

var n = {n};
var x = [], y = [], z = [];
var dt = {dt};

var s = {s};
var b = {b};
var r = {r};

for (var i = 0; i < n; i++) {{
x[i] = Math.random() * 2 - 1;
y[i] = Math.random() * 2 - 1;
z[i] = 30 + Math.random() * 10;
}}

Plotly.react('animated_plot', [{{
x: x,
y: z,
mode: 'markers',
}}], {{
xaxis: {{
range: [-40, 40],
}},
yaxis: {{
range: [0, 60],
}}
}});


function compute () {{
for (var i = 0; i < n; i++) {{
var dx = s * (y[i] - x[i]);
var dy = x[i] * (r - z[i]) - y[i];
var dz = x[i] * y[i] - b * z[i];

x[i] += dx * dt;
y[i] += dy * dt;
z[i] += dz * dt;
}}
}}

function update () {{
compute();

Plotly.animate('animated_plot', {{
data: [{{ x: x, y: z }}]
}}, {{
transition: {{ duration: 0 }},
frame: {{ duration: 0, redraw: false }}
}});

controller.frameId = requestAnimationFrame(update);
}}

controller.frameId = requestAnimationFrame(update);
}})();
</script>
"""

return ui.HTML(plot_html + loop_script)


app = App(app_ui, server)
3 changes: 3 additions & 0 deletions docs/apps/TemplatePlotly/animated_js/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
numpy
palmerpenguins
plotly
7 changes: 5 additions & 2 deletions docs/apps/TemplatePlotly/app.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ Plotly is a powerful graphing library that makes interactive, publication-qualit
## Simplest plotly plot
The following example demonstrates how to create a simple static plot using Plotly within a Shiny app
{{embed_app("100%", "550px", "static")}}
## Animations using plotly
## Animations using plotly (python)
Plotly makes it easy to create animated plots with minimal setup. The following example demonstrates how to create an animated plot using Plotly within a Shiny app.
{{embed_app("100%", "550px", "animated")}}
Note that this approach requires animations that loop smoothly. The entire frame stack must be preloaded when the plot is first rendered, which may lead to longer initial load times for complex animations. Additionally, this precludes a true "live" animation that updates based on real-time or on-the-fly generated data.
Note that this approach requires animations that loop smoothly. The entire frame stack must be preloaded when the plot is first rendered, which may lead to longer initial load times for complex animations. Additionally, this precludes a true "live" animation that updates based on real-time or on-the-fly generated data.
## Animations using plotly (injecting JavaScript)
For more advanced use cases, you can inject custom JavaScript code to control the animation behavior in Plotly directly. This allows for greater flexibility and smoother animations. The following example (from [plotly.js](https://plotly.com/javascript/animations/#animating-many-frames-quickly)) demonstrates how to create an animated plot using Plotly with custom JavaScript within a Shiny app, allowing for on-the-fly generation of new frames.
{{embed_app("100%", "550px", "animated_js")}}