Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to animate points with gridSVG in a vectorised way?

Tags:

r

svg

r-grid

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?

like image 360
Richie Cotton Avatar asked Nov 30 '25 17:11

Richie Cotton


1 Answers

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.

like image 124
joran Avatar answered Dec 03 '25 07:12

joran



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!