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 - How to draw lines between specified dots on ListPlot?

I would like to create a plot where I have unconnected dots and some connected. So far, I have figured out how to draw the dots. My code is the following: ListPlot[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4,13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full] I have thought using ListLinePlot command, but I don't know how to specify to the command to draw only selected lines between the dots. Do have any suggestions/hints on how to do that? Thank you. Answer One possibility would be to use Epilog with Line : ListPlot[ {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full, Epilog -> { Line[ ...

equation solving - Invert and fit implicitly defined curve

I need to fit an implicitly defined curve. I thought I could get some data out of Solve , and then using FindFit . Therefore, I would like to find the relation the parametric curve defined by $F(x,y)=0$: Solve[-(1/2) + 1/2 (0.41202 BesselK[0, 0.1 Sqrt[x^2 + y^2]] + (0.101483 x BesselK[1, 0.1 Sqrt[x^2 + y^2]])/Sqrt[x^2 + y^2]) == 0, y] But I can't get an output: Solve was unable to solve the system with inexact coefficients or the system obtained by direct rationalization of inexact numbers present in the system. Since many of the methods used by Solve require exact input, providing Solve with an exact version of the system may help. >> Edit: In particular, I would like to fit the data coming from the curve with the expression of another curve, and not with a function $f(x)$. In particular, since this clearly looks like a cardioid , I would like it to fit to something like it. What other strategies could I try?

dynamic - How can I make a clickable ArrayPlot that returns input?

I would like to create a dynamic ArrayPlot so that the rectangles, when clicked, provide the input. Can I use ArrayPlot for this? Or is there something else I should have to use? Answer ArrayPlot is much more than just a simple array like Grid : it represents a ranged 2D dataset, and its visualization can be finetuned by options like DataReversed and DataRange . These features make it quite complicated to reproduce the same layout and order with Grid . Here I offer AnnotatedArrayPlot which comes in handy when your dataset is more than just a flat 2D array. The dynamic interface allows highlighting individual cells and possibly interacting with them. AnnotatedArrayPlot works the same way as ArrayPlot and accepts the same options plus Enabled , HighlightCoordinates , HighlightStyle and HighlightElementFunction . data = {{Missing["HasSomeMoreData"], GrayLevel[ 1], {RGBColor[0, 1, 1], RGBColor[0, 0, 1], GrayLevel[1]}, RGBColor[0, 1, 0]}, {GrayLevel[0], GrayLevel...