-
DescriptionThis is loosely related to #6626. I'm trying to embed a matplotlib animation inside a quarto presentation. It almost works, but the layout is not behaving like expected. In the "not ok" slide, the animation and widgets are shown as expected, but there is also the last frame of the animation which is displayed on the page (which I don't want to see). This is a jupyter notebook issue and can be solved with either "solution 1" or "solution 2". The problem is that the animation widgets appear above the animation (instead of below as in "not ok" slide), which is an unpleasant layout. However, when the document is rendered in html, which I do by replacing "revealjs" by "html" in the header, the widgets are displayed below the plot as expected. Why are these two formats behaving differently? Is there another way to fix this weird layout? This should maybe be a different issue, but when I put both "revealjs" and "html" in the "format" section of the header, I cannot switch between the two outputs as the button in the top right is suggesting. Instead the button is not responsive and I stay on the same output type. I'm not sure if this is the expected behavior or I'm using it incorrectly. Thanks for your time ---
title: "Reproducible Quarto Document"
format:
revealjs:
fig-width: 4
fig-height: 3
---
## Not ok
```{python}
from IPython.display import HTML
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
```
```{python}
fig, ax = plt.subplots()
xdata, ydata = [], []
ln, = ax.plot([], [], 'ro')
def init():
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1, 1)
return ln,
def update(frame):
xdata.append(frame)
ydata.append(np.sin(frame))
ln.set_data(xdata, ydata)
return ln,
ani = FuncAnimation(fig, update, frames=np.linspace(0, 2*np.pi, 5),
init_func=init, blit=True)
HTML(ani.to_jshtml())
```
## Solution 1
```{python}
%%capture
fig2, ax2 = plt.subplots()
xdata2, ydata2 = [], []
ln2, = ax2.plot([], [], 'ro')
def init2():
ax2.set_xlim(0, 2*np.pi)
ax2.set_ylim(-1, 1)
return ln2,
def update2(frame):
xdata2.append(frame)
ydata2.append(np.sin(frame))
ln2.set_data(xdata2, ydata2)
return ln2,
ani2 = FuncAnimation(fig2, update2, frames=np.linspace(0, 2*np.pi, 5),
init_func=init2, blit=True)
```
```{python}
HTML(ani2.to_jshtml())
```
## Solution 2
```{python}
fig3, ax3 = plt.subplots()
xdata3, ydata3 = [], []
ln3, = ax3.plot([], [], 'ro')
def init3():
ax3.set_xlim(0, 2*np.pi)
ax3.set_ylim(-1, 1)
return ln3,
def update3(frame):
xdata3.append(frame)
ydata3.append(np.sin(frame))
ln3.set_data(xdata3, ydata3)
return ln3,
ani3 = FuncAnimation(fig3, update3, frames=np.linspace(0, 2*np.pi, 5),
init_func=init3, blit=True)
plt.close()
HTML(ani3.to_jshtml())
``` |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 15 replies
-
Beta Was this translation helpful? Give feedback.
Great, thanks for the clarification both of you. This helps understand what is happening.
This is because of RevealJS auto stretch feature that is on by default. (https://quarto.org/docs/presentations/revealjs/advanced.html#stretch) The hint is that this feature requires to touch the DOM in post process
If you set,
to deactivate globally
or
## Solution 1 {.nostretch}
to deactivate at slide level
then you won't see the order problem.
It seems there an issue in how we modify the DOM because the order should not be changed I believe.
However, I am wondering if opting out by default for such animation in Jupyter is a good idea maybe 🤔