Skip to main content

graphics - General techniques for creating complex animations


I love good animations of abstract concepts, and when I try to create them myself, I prefer doing so in code to make sure they are exact (and because some things are just way too fiddly to do by hand). In general, Mathematica seems like a nice tool for this, because of its powerful plotting capabilities. My problem is that this tends to get quite annoying once my animation consists of multiple "phases", which cannot all be easily described by a single continuous function.


To give you an idea of what I mean, here are some examples from a very popular question over on Math.SE:



Source




Source


Note that I'm specifically not talking about animations like the one in the top-voted answer, which can easily be expressed as a large number of graphics primitives whose parameters are continuous functions of some time parameter t.


In the two examples above there are lots of different steps to the animation. Objects appear, disappear or undergo qualitatively different motions over their lifetime (like growing, bending, rotating, translating). I find setting up these animations quite cumbersome (to the extent that when I do manage it, I can no longer be bothered to improve the timing of the animation of add ease-in/out effects to the motions). I usually take some approach with creating fiddly Piecewise functions of bunches of If or Which statements. Whatever I do, it's very ad hoc.


As an example, I've tried to recreate the second GIF above. I didn't even bother with the red flashing and a particularly nice presentation, but all movements are there:


Table[Graphics[{
Line[{{0, 0}, {1, 0}}],
Line[{{1, -.1}, {1, .1}}],
Text[1, {1, -.2}],
If[t > 0.5, {
Line[{{1, 0}, {2, 0}}],

Line[{{2, -.1}, {2, .1}}],
Text[2, {2, -.2}]
}, {}],
If[t > 1, {
Line[{{0, 0}, ReIm@Exp[I*Min[1, t - 1] Pi/2]}]
}, {}],
If[t > 2, {
Text[1, {-.1, .5}],
Arrow[{{-.1, 0.35}, {-.1, 0}}],
Arrow[{{-.1, 0.65}, {-.1, 1}}],

Line[{{.5, -.1}, {.5, .1}}],
Text["1/2", {.5, -.2}],
Line[{{1.5, -.1}, {1.5, .1}}],
Text["3/2", {1.5, -.2}]
}, {}],
If[2 < t <= 3.5, {
Red,
Line[{{.5, 0}, {.5, 0} + ({0, 1} - {.5, 0}) Min[1, t - 2]}]
}, {}],
If[t > 3.5, {

Red,
Line[{{.5, 0}, {.5, 0} +
Sqrt@5/2*ReIm@Exp[I*(Pi - ArcTan@2) (1 - Min[1, t - 3.5])]}]
}, {}],
If[t > 4.5, {
Arrow[{{GoldenRatio, 0.35}, {GoldenRatio, 0.05}}],
Text["\[Phi] \[TildeTilde] 1.1618", {GoldenRatio, 0.5}]
}, {}]
},
PlotRange -> {{-0.25, 2.25}, {-0.25, 1.25}}], {t, 0, 5.5, 0.04}]


This creates a list of frames which you can then stuff into ListAnimate or Export. Here is the result:


enter image description here


My main problems are:



  • The cumbersome structure of defining hardcoded time ranges. If I decide I want to shorten or lengthen some segment, it will effect the "time codes" of all subsequent animations.

  • Repeated things like Min[1, t - 2] which I need to get a nice parameter that goes from 0 to 1 at some later time.

  • Notice that the growing red line is not the same primitive as the rotating red line, although I guess I could have combined them at the expense of even more unclarity. How can easily apply a series of transformation to the same object over time, in a clear way?

  • Not very apparent in this example, but often some transformations work better in certain local coordinate systems (e.g. rotation an object about its centre after the animation has moved it away from the origin). Are there easy ways to compose the animations in such a way that I can always pick the most convenient coordinate system for composing a sequence of transformations?

  • In this example, I've got a ton of repeated frames when nothing is happening for half a second. Of course, this could be fixed, and then I could use a custom DisplayDurations list for Export, but that makes the construction of the frames even more horrible. How can I work around this?


  • I haven't even bothered with elements fading in and out like they do in the first example above, because that would add yet another extra transformation (with hardcoded times) for every single object.


All in all, what are general techniques to make the process of creating such animations with Mathematica more straightforward with particular focus on allowing me to focus more on styling and optimising the timing/trajectories of individual segments?


Another example of types of animations which I'd love to be able to create in a simple way are Animated Mathematica Functions. Apart from the fact that they're animating text, in overall style they're very similar to the above animations. They also raise the question of how to deal with text in a convenient way, for example when you want to "duplicate" part of a string, like when the a, b, c, x are "pulled out" of the function call in the Append animation.


(If the consensus of the answer turns out to be "Mathematica isn't the perfect tool for this", I'd be happy to hear about alternatives in answers or comments, but I'm sure it must be possible to get some decent results with Mathematica.)




Comments

Popular posts from this blog

plotting - Plot 4D data with color as 4th dimension

I have a list of 4D data (x position, y position, amplitude, wavelength). I want to plot x, y, and amplitude on a 3D plot and have the color of the points correspond to the wavelength. I have seen many examples using functions to define color but my wavelength cannot be expressed by an analytic function. Is there a simple way to do this? Answer Here a another possible way to visualize 4D data: data = Flatten[Table[{x, y, x^2 + y^2, Sin[x - y]}, {x, -Pi, Pi,Pi/10}, {y,-Pi,Pi, Pi/10}], 1]; You can use the function Point along with VertexColors . Now the points are places using the first three elements and the color is determined by the fourth. In this case I used Hue, but you can use whatever you prefer. Graphics3D[ Point[data[[All, 1 ;; 3]], VertexColors -> Hue /@ data[[All, 4]]], Axes -> True, BoxRatios -> {1, 1, 1/GoldenRatio}]

plotting - Filling between two spheres in SphericalPlot3D

Manipulate[ SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, Mesh -> None, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], {n, 0, 1}] I cant' seem to be able to make a filling between two spheres. I've already tried the obvious Filling -> {1 -> {2}} but Mathematica doesn't seem to like that option. Is there any easy way around this or ... Answer There is no built-in filling in SphericalPlot3D . One option is to use ParametricPlot3D to draw the surfaces between the two shells: Manipulate[ Show[SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], ParametricPlot3D[{ r {Sin[t] Cos[1.5 Pi], Sin[t] Sin[1.5 Pi], Cos[t]}, r {Sin[t] Cos[0 Pi], Sin[t] Sin[0 Pi], Cos[t]}}, {r, 1, 2 - n}, {t, 0, Pi}, PlotStyle -> Yellow, Mesh -> {2, 15}]], {n, 0, 1}]

plotting - Mathematica: 3D plot based on combined 2D graphs

I have several sigmoidal fits to 3 different datasets, with mean fit predictions plus the 95% confidence limits (not symmetrical around the mean) and the actual data. I would now like to show these different 2D plots projected in 3D as in but then using proper perspective. In the link here they give some solutions to combine the plots using isometric perspective, but I would like to use proper 3 point perspective. Any thoughts? Also any way to show the mean points per time point for each series plus or minus the standard error on the mean would be cool too, either using points+vertical bars, or using spheres plus tubes. Below are some test data and the fit function I am using. Note that I am working on a logit(proportion) scale and that the final vertical scale is Log10(percentage). (* some test data *) data = Table[Null, {i, 4}]; data[[1]] = {{1, -5.8}, {2, -5.4}, {3, -0.8}, {4, -0.2}, {5, 4.6}, {1, -6.4}, {2, -5.6}, {3, -0.7}, {4, 0.04}, {5, 1.0}, {1, -6.8}, {2, -4.7}, {3, -1....