# Does TikZ support interactive animation?

I am plotting a function y = a*x^2 with a is variable constant. I would like to control a interactively but I google and seems that TikZ doesn't support interactive operation.

Also, I want to know if there is any way to draw some points within the function and moving randomly?

-

## 2 Answers

Actually, IMHO these could be seen as two different questions.

So, let's start with the first one:

I am plotting a function y = a*x^2 with a is variable constant. I would like to control a interactively but I google and seems that TikZ doesn't support interactive operation.

I would use for this the wonderful ocgx package in combination with pgfplots; along the site you can find already some examples:

The code:

\documentclass{article}

\usepackage{pgfplots}
\usetikzlibrary{ocgx}
\tikzset{ocg button/.style={circle,inner sep=.25em,switch ocg with mark on={#1}{}}}
\tikzset{base/.style={baseline=-0.5ex}}

\newcommand{\function}{\x^2}
\newcommand{\button}[2]{\tikz[base]\node[fill=#2!30,ocg button=#1]{};}
\newcommand{\plotit}[2]{\addplot+[ocg={name=#2,ref=#2}]{#1};\label{#2}}
\newcommand{\legendit}[3]{\item[\ref{#1}] #2$x^2$ \button{#1}{#3}}

\begin{document}
\begin{minipage}[b][0.4\textheight][l]{0.7\textwidth}
\begin{tikzpicture}
\begin{axis}[grid= major,xlabel=$x$,
ylabel =$y$,
ylabel style={rotate=-90},
cycle list={blue,red,green!50!lime,orange,cyan!50!blue},
]
\plotit{\function}{first}
\plotit{1.5*\function}{second}
\plotit{2.25*\function}{third}
\plotit{3*\function}{fourth}
\plotit{5*\function}{fifth}
\end{axis}
\end{tikzpicture}
\end{minipage}%
\begin{minipage}[b][0.5\textheight][c]{0.2\textwidth}
\begin{itemize}
\legendit{first}{}{blue}
\legendit{second}{1.5}{red}
\legendit{third}{2.25}{green!50!lime}
\legendit{fourth}{3}{orange}
\legendit{fifth}{5}{cyan!50!blue}
\end{itemize}
\end{minipage}%

\end{document}​


The result (clicking on the second and fourth button):

### Disclaimer

This works for me under Evince (standard version coming with Ubuntu 12.10) and Acrobat Reader.

Let's now come to the second question:

Also, I want to know if there is any way to draw some points within the function and moving randomly?

For this, I would use the standalone class with option tikz and place sequentially the points along the plot with the facility

node[<some opitons>, pos=<position along the plot>]


where <position along the plot> should be some number from 0 to 1.

An example:

\documentclass[tikz]{standalone}
\usepackage{pgfplots}

\begin{document}
\foreach \pos in {0,0.05,...,1.05}{
\begin{tikzpicture}
\begin{axis}[grid= major,xlabel=$x$,
ylabel =$y$,
ylabel style={rotate=-90},
no marks,
]

\addplot{\x^2}
node[fill=orange,draw=blue,circle,inner sep=1pt, pos=\pos]{}
;
\end{axis}
\end{tikzpicture}
}
\end{document}


The result:

If you want random points, just change the list inside

\foreach \pos in {0,0.05,...,1.05}


where with change I mean you have to shuffle the order (that for simplicity I did not).

One remark: the list ends in 1.05 and not 1 to correctly display the final point.

To have random points inside the plot there are basically two ways: the first one is again by means of the standalone class (a couple of examples are in the answers of Draw a closed liquid-droped shaped curve with TikZ) while the second one exploits the Beamer class; with the styles defined in Highlighting in beamer using TikZ nodes it is possible to locate some nodes specifying the moment in which they appear: this creates a sort of randomicity.

The code:

\documentclass{beamer}
\usepackage{lmodern}
\usepackage{pgfplots}

\tikzset{
invisible/.style={opacity=0,text opacity=0},
visible on/.style={alt=#1{}{invisible}},
alt/.code args={<#1>#2#3}{%
\alt<#1>{\pgfkeysalso{#2}}{\pgfkeysalso{#3}}
},
}

% http://tex.stackexchange.com/questions/84513/highlighting-in-beamer-using-tikz-nodes/84608#84608
\tikzset{
background filldraw/.style args={#1 and #2}{draw=#1, fill=#2},
background filldraw/.default={white and white},
filldraw on/.style={alt=#1{}{background filldraw}},
}

\begin{document}
\begin{frame}{}
\begin{tikzpicture}
\begin{axis}[grid= major,xlabel=$x$,
ylabel =$y$,
ylabel style={rotate=-90},
no marks,
]

\addplot{\x^2};

\end{axis}
\foreach \pos/\moment in {{(4,4)}/{1,3,5,6},{(2,2)}/{2,3,4,8},
{(1.5,4)}/{2,4,5,7},{(5,3)}/{1,2,3,5,8},{(2.5,1.5)}/{2,4,5,6},
{(1.75,3.5)}/{1,3,6,8},{(3.75,2.5)}/{2,5,7,8},{(3.75,1.25)}/{2,3,4,5,6}}{
\node[circle, inner sep=1.5pt,
background filldraw={blue and orange},
filldraw on=<\moment>] at \pos {};
}
\end{tikzpicture}
\end{frame}
\end{document}


The result:

-
Thank you so much for your code. It solves partial of my question. I just wonder if there is any way to add a control bar to control the parameter a. Let say the control bar range from 1 to 3 with step 0.2, so to plot the curve with specific a one at a time when sliding the control bar. Aslo I want to plot a bunch of points random walking inside bound area of the curve not on the curve. What I am try to see is something like the animation in the middle of colorado.edu/physics/2000/bec/what_is_it.html –  user1285419 Feb 17 '13 at 3:00
Unfortunately I don't believe it's possible to create a control bar interactive. Instead, I guess plot random walking points is perfectly doable, so I will upload a solution for that. –  Claudio Fiandrino Feb 17 '13 at 9:48
Thanks Claudio, your code looks pretty neat. Just one thing, in the first example, I would like to shown one curve at a time, i.e. if I click one button, it show me the curve of current parameter and hide all other curves. Also, I also want to shown the forever randomly walking points inside the curve (bowl) at the same frame until and unless I make any click to change curve. I am following your example, but I don't make it yet. –  user1285419 Feb 17 '13 at 10:07
@user1285419: if you first disable all curves by clicking all the buttons, then you can enable just one at a time: this will let you to achieve the goal. I'm making an example for the other issue. –  Claudio Fiandrino Feb 17 '13 at 18:42
I might not put that clear, what I mean is to show one curve at a time and when one curve shown, hide all others. I am trying to combine the technique described in the first link tex.stackexchange.com/questions/65096/… wit \newframe and use \GoToFrame to implement this effect. I would like to use your code to show the curves and use that code to hide all other curves when one was shown, but not success. –  user1285419 Feb 17 '13 at 20:27

Real interactivity in the sense that you can smoothly modify parameters of a plotted function is beyond the possibilities of the PDF standard. However, the PDF standard allows for interactive elements embedded into the document, namely the RichMedia Annotation, which delegate display and user-interaction to a plug-in. Only AdobeReader currently implements the RichMedia Annotation and it uses FlashPlayer for rendering the graphical material inside the annotation area.

Interactive applications must therefore be in the Flash (SWF) format. It can be produced, e. g., with the now open-source Flex-SDK. The SWF produced can be embedded into the PDF using the media9 package.

The example uses the LineChart and HSlider components of Flex.

\documentclass[12pt]{article}
\usepackage{media9}

\begin{document}

\section{Interactive function plot example}

$$y=a x^2$$

\noindent\includemedia[
width=\linewidth,height=1.1\linewidth,
activate=pageopen
]{}{bec.swf}
\end{document}


The embedded Flash file bec.swf (visualizing something looking like a Bose-Einstein Condensate, as the topic poster requested) was compiled from the Flex source file bec.mxml listed below, using the mxmlc compiler from the Flex-SDK.

<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
initialize="init();">

<mx:Script><![CDATA[
import mx.collections.ArrayCollection;
import flash.utils.Timer;
import flash.events.TimerEvent;

[Bindable] private var quadFunc:ArrayCollection = new ArrayCollection();
[Bindable] private var atoms:ArrayCollection = new ArrayCollection();
private var xMax:Number=10;
private var yMax:Number=300;
private var updateTimer:Timer;

public function atomPositions(e:TimerEvent):void {
atoms.removeAll();
var yM:Number=aSlider.value*xMax*xMax;

for (var i:Number = 0; i<50; i++){
var y:Number=Math.random()*yM;
var x:Number=(Math.random()*2-1)*Math.sqrt(y/aSlider.value);
atoms.addItem({xPos:x, yPos:y});
}
}

public function change():void {
quadFunc.removeAll();
for (var i:Number = -xMax; i<=xMax; i+=0.1){
var yVal:Number=aSlider.value*i*i;
quadFunc.addItem({xVal:i, yVal:yVal});
}
atomPositions(null);
}

public function init():void {
haxis.minimum=-xMax;
haxis.maximum=xMax;
vaxis.maximum=yMax;

change();
updateTimer = new Timer(50,0);
updateTimer.addEventListener("timer", atomPositions);
updateTimer.start();
}
]]></mx:Script>

<mx:LineChart id="chart" width="100%" height="100%"
showDataTips="true">
<mx:horizontalAxis>
<mx:LinearAxis id="haxis"/>
</mx:horizontalAxis>
<mx:verticalAxis>
<mx:LinearAxis id="vaxis" minimum="-2"/>
</mx:verticalAxis>
<mx:series>
<mx:LineSeries xField="xVal" yField="yVal" form="curve"
dataProvider="{quadFunc}"/>
<mx:PlotSeries xField="xPos" yField="yPos" dataProvider="{atoms}"
itemRenderer="mx.charts.renderers.CircleItemRenderer"/>
</mx:series>
</mx:LineChart>
<mx:HSlider id="aSlider" width="100%"
minimum="0.1" maximum="3" value="0.1"
dataTipPlacement="top"
snapInterval="0.01" tickInterval="0"
labels="[a=0.1,3]"
allowTrackClick="true"
liveDragging="true"
change="change();"/>
</mx:Application>


-
Nice! Flash is known for its security problems: do you think that it will get better now that it is somehow open source? –  pluton Feb 18 '13 at 13:52
@pluton: Since it is you who writes the Flash app to be embedded, you should have full control over what it actually does. The mxmlc compiler has a command line option to impede the SWF to access files and resources on the internet. Ready SWF files found on the internet and embedded into PDF are of course a different kettle of fish. –  AlexG Feb 18 '13 at 14:22