I'm getting started learning how to use the gridSVG
package to create animated SVG plots. As a test, I want to animate a set of points, moving from start positions to finish positions. The example is loosely based upon those in the package's first vignette.
First, some data:
n_points <- 20
start <- data.frame(
x = runif(n_points),
y = runif(n_points)
)
end <- data.frame(
x = runif(n_points),
y = runif(n_points)
)
The basic idea seems to be "draw a new page, add the contents for the first frame, animate, then save to SVG". My first attempt draws all the points in the same place. I'm not sure how to tell grid.animate
that each point needs to be moved individually.
grid.newpage()
with(start,
grid.points(x, y, default.units = "npc", name = "points")
)
grid.animate(
"points",
x = c(start$x, end$x),
y = c(start$y, end$y)
)
gridToSVG("point_test1.svg")
I can get round this by drawing each point in its own grob, using lapply
. This works, but feels clunky – there ought to be a vectorised way of doing it.
grid.newpage()
lapply(seq_len(n_points), function(i)
{
gname = paste("points", i, sep = ".")
with(start,
grid.points(x[i], y[i], default.units = "npc", name = gname)
)
grid.animate(
gname,
x = c(start$x[i], end$x[i]),
y = c(start$y[i], end$y[i])
)
})
gridToSVG("point_test2.svg")
I also tried using animUnit
, but I can't figure out how to specify the id
parameter.
grid.newpage()
with(start,
grid.points(x, y, default.units = "npc", name = "points")
)
x_points <- animUnit(
unit(c(start$x, end$x), "npc"),
timeid = rep(1:2, each = n_points),
id = rep(1:2, n_points)
)
y_points <- animUnit(
unit(c(start$y, end$y), "npc"),
timeid = rep(1:2, each = n_points),
id = rep(1:2, n_points)
)
grid.animate( #throws an error: Expecting only one value per time point
"points",
x = x_points,
y = y_points
)
gridToSVG("point_test3.svg")
Can I animate multiple points inside a single grob, or otherwise animate points without a loop?
This works for me using animUnit
:
grid.newpage()
with(start,
grid.points(x, y, default.units = "npc", name = "points")
)
x_points <- animUnit(
unit(c(start$x, end$x), "npc"),
#timeid = rep(1:2, each = n_points),
id = rep(1:20, 2)
)
y_points <- animUnit(
unit(c(start$y, end$y), "npc"),
#timeid = rep(1:2, each = n_points),
id = rep(1:20, 2)
)
grid.animate( #throws an error: Expecting only one value per time point
"points",
x = x_points,
y = y_points
)
You were specifying id's for two points, rather than twenty. My reading of the vignette is that for animating multiple grobs with a single x value per grob, you only need to specify the id.