\documentclass[a4paper]{article} %\VignetteIndexEntry{animation} \newcommand{\grid}{{\bf grid}} \newcommand{\gridSVG}{{\sf gridSVG}} \newcommand{\lattice}{{\bf lattice}} \newcommand{\R}{{\sf R}} \newcommand{\code}[1]{{\tt #1}} \setlength{\parindent}{0in} \setlength{\parskip}{.1in} \title{Animation with the gridSVG package} \author{Paul Murrell} \begin{document} \maketitle @ \section*{Introduction} The \code{grid.animate()} function in the \gridSVG{} package allows various features of a \grid{} grob to be animated. Calls to this function can be quite straightforward. For example, the following code animates a circle so that it travels from left to right across the screen (the result of this code is the file \code{"animCircle.svg"}, which can be viewed in a web browser). <<>>= library(grid) library(gridSVG) @ <>= grid.circle(.1, .5, r=.1, gp=gpar(fill="black"), name="circle") grid.animate("circle", x=c(.1, .9)) grid.export("animCircle.svg") @ Things can get more complicated though. For example, in order to animate a \code{polyline} grob, it is necessary to specify a \emph{vector} of \code{x} and/or \code{y} locations for each time point \emph{and} it may even be necessary to specify \emph{multiple} vectors at each time point if the \code{polyline} grob specifies more than one polyline (via its \code{id} argument). To give a concrete example, consider the result of the following \grid{} code, which draws two polylines from a single call to \code{grid.polyline()} (see Figure \ref{figure:polyline}). <>= grid.rect() grid.polyline(c(.2, .3, .4, .6, .7, .8), c(.7, .5, .7, .3, .5, .3), id=rep(1:2, each=3), gp=gpar(lwd=5), name="polyline") @ \begin{figure} <>= <> @ \caption{\label{figure:polyline}Two polylines drawn from a single call to \code{grid.polyline}.} \end{figure} The task is to animate the two polylines so that they appear to ``flap'' (the left will transition to look like the right one and the right one will transition to look like the left one, and repeat). The y-values for the animation look something like this (the x-values are not animated): <>= polylineY <- animUnit(unit(c(.7, .5, .7, .3, .5, .3, .3, .5, .3, .7, .5, .7, .7, .5, .7, .3, .5, .3), unit="npc"), timeid=rep(1:3, each=6), id=rep(rep(1:2, each=3), 3)) @ <>= polylineY @ For the first polyline (\code{id1}), at the first time point (\code{t1}), the y-values are just the original y-values, \code{c(.7, .5, .7)}. At the second time point, the y-values for the first polyline are \code{c(.3, .5, .3)}, and at the third time point the y-values are back to the original \code{c(.7, .5, .7)}. The y-values for the second polyline are the reverse of the y-values for the first polyline. Specifying this set of animation values is more complex and can get pretty confusing, but at the same time, we still want to be able to specify the simple animation values (like in the first example) in a simple manner. The \gridSVG{} package provides a consistent, but flexible system for specifying animation values that is based on a single, coherent data structure, but which allows the user to use simpler specifications where possible. \section*{The \code{animUnit} class} An \code{animUnit} object has three components: a vector of \code{values} (as a \code{unit} object), a \code{timeid} vector (default \code{NULL}), and an \code{id} vector (default \code{NULL}). The \code{animUnit()} function is used to create an \code{animUnit}, with only the \code{values} as a required argument. The following code generates a single value at four different time points. <<>>= animUnit(unit(1:4, "cm")) @ As this example shows, the default interpretation of a \code{NULL} \code{timeid} is that each value belongs to a separate time period (and the default interpretation of a \code{NULL} \code{id} is that there is only one shape to be animated). This example also demonstrates the \code{print} method for \code{animUnit} objects, which is useful for seeing which animation values belong to different time periods. This simple sort of \code{animUnit} is sufficient for specifying something like the x-location of a single data symbol (where there is exactly one x-value required per time point). For the slightly more difficult situation of animating multiple data symbols (where we need several x-values per time period, one for each different data symbol), the \code{id} argument can be explicitly specified. The following code generate values for two shapes (\code{id1} and \code{id2}) with values at two time points (\code{t1} and \code{t2}) for each shape. <<>>= animUnit(unit(1:4, "cm"), id=rep(1:2, 2)) @ In the case where we have a single shape, but that shape is described by multiple x-values (e.g., a single polygon), we need multiple x-values per time point \emph{for each shape}, the \code{timeid} argument can be used to associate multiple x-values with a single time point. The following code generates six values at each of two time points (\code{t1} and \code{t2}) for a single shape. <<>>= animUnit(unit(1:12, "cm"), timeid=rep(1:2, 6)) @ And in the worst case, we have multiple shapes, each requiring multiple x-values per time period (e.g., multiple polygons from a single \code{polygon} grob), so we need to specify \emph{both} \code{id} and \code{timeid}. The following code generates three values at two different time points for two different shapes. <<>>= animUnit(unit(1:12, "cm"), timeid=rep(1:2, 6), id=rep(1:2, each=6)) @ The following code uses the \code{animUnit()} function to produce the flapping polylines example from the previous section. It produces a file called \code{"animPolyline.svg"} that can be viewed in a browser. <>= grid.animate("polyline", y=polylineY, rep=TRUE) @ <>= grid.newpage() <> <> <> grid.export("animPolyline.svg") @ \section*{The \code{as.animUnit()} function} The \code{animUnit} class gives us the range of possible specifications that we require, but it is overkill for simple cases, and may be less convenient even for more complex cases. There is an \code{as.animUnit()} function that can convert vectors, matrices, and lists to \code{animUnit}s so that we can use those simpler data structures to provide animation values. For example, a single value per time period can be specified with just a vector, as follows. <<>>= as.animUnit(1:4, unit="cm") @ Even better, the \code{grid.animate()} function makes use of this coercion function and fills in the \code{unit} based on the units of the feature that is being animated. This means that the call to \code{grid.animate()} can just specify a vector, like the following (taken from the first example at the beginning of this document). <>= grid.animate("circle", x=c(.1, .9)) @ When we need to specify values for multiple shapes it can be convenient to use a matrix, where each column provides the values for a different shape. The following code shows an example (again, in a call to \code{grid.animate()} we can leave out the \code{unit}). <<>>= m <- matrix(1:6, ncol=2) m @ <<>>= as.animUnit(m, unit="cm") @ If we have multiple values per time point (e.g., a polygon), we can get \code{as.animUnit()} to treat columns as different time points rather than as different shapes by specifying the \code{multVal} argument, as shown below. <<>>= as.animUnit(m, unit="cm", multVal=TRUE) @ The \code{grid.animate()} function guesses how it should use the columns of a matrix, depending on the shape that is being animated, so for relatively straightforward cases we should be abe to simply pass a matrix to \code{grid.animate()}. Finally, we can specify animation values as a list of units (if that is more convenient than calling \code{animUnit()}). The following code shows an example, which shows that the default behaviour is to treat each component of the list as animation values for a separate shape. <<>>= l <- list(unit(1:3, "cm"), unit(4:6, "cm")) l @ <<>>= as.animUnit(l) @ Again, we can specify that the components of the list correspond to separate time points rather than separate shapes (by calling \code{as.animUnit()} directly and supplying the \code{multVal} argument). <<>>= as.animUnit(l, multVal=TRUE) @ \section*{The \code{animValue} class} Some features of a shape, such as \code{visibility}, are not numeric locations or dimensions, so they do not need to be specified as unit values. For these cases, there is an \code{animValue()} function to create the various specifications that we might need, plus an \code{as.animValue()} function, which \code{grid.animate()} makes use of to allow convenient variations. \section*{Summary} For relatively simple animations, all we need to do is specify a numeric vector, or possibly a matrix, in the call to \code{grid.animate()}. For more complex animations, how we specify the animation values depends on what we find most convenient. Specifying a matrix or a list of units may suffice, although this may rely on \code{grid.animate()} correctly guessing our intention. It may be necessary to directly call \code{as.animUnit()} on a matrix or a list of units to get the behaviour that we want. Alternatively, a direct call to \code{animUnit()} should allow us to specify any set of animation values that we need and the \code{print()} method for the \code{animUnit} objects that are created by that function should help us to check that we are generating values in the right format. \end{document}