====== Animations Module ====== This example shows how you can use multiple frames of an animation within a single image object to create animations. The animation in the example is of a light turning on and off. The animation frames are provided by [[http://www.customcodecrafters.com/section/17/1/graphics|Custom Code Crafters]] Updated to now also include a simple loading spinner using a single image and rotating the image object via JavaScript CF.setProperties. [[https://github.com/CommandFusion/DemoUserInterfaces/tree/master/Animated%20Icon|View on GitHub]].\\ \\ [[https://github.com/downloads/CommandFusion/DemoUserInterfaces/Animated%20Icon.zip|Download project from GitHub]]. Please note that the below information is out of date and is the old method. This can be used as an alternative to using JavaScript if required. The above demo GUI is the latest method. Although guiDesigner does not have a built in animation object, the same result can be achieved by using Timers and Feedback Parsing. ===== Downloads ===== {{:software:gui-designer:example-gui-projects:anim.gui.zip|Animation Demo guiDesigner Project}} ===== Setting Up The Animation Frames ===== The first step in setting up your animation is to have each frame as a separate image (we recommend using PNG always for its alpha transparency).\\ You need to make sure each image in the animation will be cached to the device, so to do this we use a Cache Page. In the demo the cache page is actually a subpage, which contains all the frames of the animation so we can recall them dynamically. Then you place the first frame of the animation (or any image placeholder) into your page where you want the animation to show. This image needs to be given a serial join so that we can dynamically change its file path. ===== Setting Up The Timers And Loopback System ===== Once you have the animation images all setup, you need to program how the image will be animated.\\ The way to do this is via a Timer on the page/subpage that contains the animation placeholder image. But before you create a timer, you need to create the command that the timer will send. ==== Creating the System ==== First you must create the System in the System Manager, using the standard loopback system details (127.0.0.1, any port, UDP, maintain constant connection The loopback system allows you to send commands from the Viewer directly back to itself. ==== Creating the timer Command ==== Next we need to create a command to send via the timer, which will be used to increment the frames in the animation.\\ To create the command, click on the system created earlier, then press the 'Add new Command' button in the System Manager toolbar.\\ Give the command a name, like 'loading' and a value that will be parsed and used to define what image frame we want to show in the animation. In the example, the command sends 'loading=loading_[load].png'. ==== Creating the Global Token ==== Notice that we have embedded a Global Token into the command called [load]. This allows us to increment the token value each time and assign which frame to display in the image object.\\ You will also want to setup a default Global Token value within the Project Properties > Global Token Properties. Just create a token called [load] with a default value of 1 (this could be any number, depending on which frame you want to start at in the animation).\\ So the first time the command is sent in our example, it will actually send 'loading=loading_1.png'. Creating the Timer Now we need to setup the Timer to send the command, so right click on the page/subpage name in the [[software:gui-designer:project-tree|project tree]] and choose 'Setup Page Timers...'.\\ Add a new timer, giving it an analog join (which we can use to speed up, slow down, stop or start the animation). Then set the interval to 0 if you want the animation to be paused on startup (you could have the animation running instantly on startup by setting this to a value like 50. This is the speed at which the frames will animate. Set the repeat count to zero so that it loops the animation continuously. ==== Creating the Feedback Parsing ==== When the timers sends its command, we need to parse the data and increment the global token. The first step is to create a regex that matches the incoming data so that we can assign the value to both the serial join of the image object and the global token.\\ In our example, the regex is 'loading=(loading_(\d+).png)'. This creates two capture groups: The first grabs the entire 'loading_#.png' string, whilst the second just grabs the #.\\ With the first capture group we just assign its value to the image object's serial join. This will set the image to the path 'loading_1.png' for the first frame.\\ With the second capture group, we want to grab the number and apply some math to it and assign the result to the Global token [load].\\ First we want to increment the number by 1 to show the next frame, but we also need to ensure once it gets to the last frame that it loops back to the start as this is a continuous looping animation.\\ To do this we use the modulo math symbol (%) in our expression. Our animation has 20 frames, so the math is: 1+(value%20)\\ So this new value is assigned to the [load] token, ready to send the next frame of the animation the next time the Timer fires. So in effect, the Timer is going to send a different value each time, such as: * loading=loading_1.png * loading=loading_2.png * loading=loading_3.png * . * . * loading=loading_20.png * loading=loading_1.png ==== Creating the Start and Stop Commands ==== In our example, we initially have the animation stopped (done by setting the Timer interval to zero). So we need a way to start it and stop it again.\\ Create two command, one called 'loading_start' one called 'loading_stop'. These commands can have any value, as the value wont actually be used for anything. So instead, we want to set the Timer interval to a certain speed for the animation when starting, and back to zero when stopping.\\ We do this by selecting the 'optional assign target value' option in the command properties. We want to target the analog join that we assigned to the Timer earlier. By adjusting the value of the timer's analog join, we are adjusting the speed at which the timer fires, and hence the speed of the animation. Zero means to stop the Timer, and hence stop the animation.\\ Next create some buttons to assign the start and stop commands to. ===== Summary ===== Thats about all there is to it. So to recap, here is how we do animation in guiDesigner: - Create the image frames of the animation and add them to a cache page - Create the image placeholder for the animation somewhere in your GUI - Create a loopback system, with commands and feedback for incrementing the frame, starting and stopping the animation - Create a Global Token to track the current animation frame - Assign the start and stop commands to some buttons