AnimationFrameListener
signals once the beginning of a browser's frame (depends on OS settings, hardware). It can be reloaded again after any changes of dependent dynamic symbols similar to requestAnimationFrame
.
The main idea is
- to be in sync with a beginning of native browser's frame drawing
- to animate something as fast as possible
- don't fire next frame, before calculations are done
Therefore this provides a balanced load to the system.
AnimationFrameListener[trigger_Offload, "Event"->event_String]
where trigger
can be any dynamic symbol wrapped in Offload, that will be changed each frame, it serves the purpose of a signal, that all calculations are done. event
is a string representation of EventObject
to which a handler function, that recalculates trigger
is assigned.
Example
There is a famous example of 1000 particles "dancing" with each other
n = 1000;
r := RandomInteger[{1, n}];
f := (#/(.01 + Sqrt[#.#])) & /@ (x[[#]] - x) &;
s := With[{r1 = r}, p[[r1]] = r; q[[r1]] = r];
x = RandomReal[{-1, 1}, {n, 2}];
{p, q} = RandomInteger[{1, n}, {2, n}];
EventHandler["frame", Function[Null,
(* all calculations *)
x = 0.995 x + 0.02 f[p] - 0.01 f[q];
If[r < 100, s];
]];
Graphics[{
PointSize[0.007], Point[x // Offload],
AnimationFrameListener[x // Offload, "Event"->"frame"]
}, PlotRange -> {{-2,2}, {-2,2}}, "TransitionType"->"Linear", "TransitionDuration"->1]
Here we used the same symbol x
used for drawing our points for triggering AnimationFrameListener. It does not cost anything, since it listens only for change of a symbol and does not read or decode an actual value.
to cancel animation - remove handler
EventRemove["frame"]
and to restart - evaluate cell 2 and retrigger it using
EventFire["frame", True];