---
title: "Animation"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{Animation}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>"
)
```
```{r setup, echo = FALSE}
library(nara)
```
Animating with `{nara}` is simply a matter of generating and displaying
multiple images - hopefully quickly enough to look smooth.
There are two approaches:
1. Render all the images into a list, and then save as a video file e.g. `.gif`, `.mp4`
2. Display the images to a fast graphics device
## Render to a video file
To render to a video file, `{nara}` use `nrs_to_gif()` and `nrs_to_mp4()`.
These functions are simple wrappers around the
[`{magick}`](https://cran.r-project.org/package=magick) package.
The code below:
* sets up `N` circles with positions and velocities
* for each frame
* create a new image
* advance the circle positions
* draw circles
* add image to the list of all images
* saves the list of images to a `.gif`
```{r eval=FALSE}
library(nara)
w <- 320
h <- 200
set.seed(1)
N <- 20
xs <- runif(N, 0, w)
ys <- runif(N, 0, h)
rs <- runif(N, 2, 6)
vx <- rnorm(N, sd = 3)
cols <- sample(heat.colors(N))
# Storage for animation frames
anim <- list()
for (i in seq(30)) {
# create image
nr <- nr_new(w, h, fill = 'grey90')
# update the x position and wraparound
xs <- xs + vx
xs <- ifelse(xs < 0, xs + w, xs)
xs <- ifelse(xs > w, xs - w, xs)
# draw circles
nr_circle(nr, xs, ys, rs, cols)
# store animatino frame
anim[[i]] <- nr
}
nrs_to_gif(anim, "working/demo.gif")
# nrs_to_mp4(anim, "working/demo.mp4")
```
## Render to a fast graphics device
If your graphics device updates fast enough, then you can show images on this
device quickly and have the appearance on smooth animation.
A major problem for most platforms: **Rstudio and Positron graphics devices
are not fast enough to do this**
Instead, if you are wanting to use a built-in graphics device, the
`x11()` device is the preferred graphics output for animation.
`x11()` device is supported on macos, linux and windows (where it a lightweight
wrapper around the standard `windows()` device).
A good way to setup this device for fast animation is to:
1. Call `x11()`
2. Set the type to double buffered Cairo rendering `type = 'dbcairo'`
3. Disable the *display list* as there's no need to record graphics operations
4. Use `dev.hold()` and `dev.flush()` calls to synchronise the drawing command
with the graphics display update (this can prevent tearing).
5. A small pause may be needed in the loop, otherwise things might go *too* fast!
See code below for an example:
```{r eval=FALSE}
x11(..., type = 'dbcairo', antialias = 'none')
dev.control(displaylist = 'inhibit')
for (i in seq(nframes)) {
nr <- generate_image_somehow()
dev.hold()
plot(nr)
dev.flush()
Sys.sleep(0.03) # Sleep maybe?
}
```
Note: Particular platforms may have differing parameters to give good results for
realtime animation - you might need to experiment to get the best out of your
platform.