Animating between two data sets

In this recipe we will animate the transition when switching between two data sets. We will show how to animate without using any libraries. To do so we will use the bar chart as a base. We are going to start by fading in the chart. After that, we will grow the bars until they reach their desired size. In order to animate the switch between the two data sets, we will first shrink the current bars until we can't see them so that we can expand the new bars after.

Getting ready

Copy over the files from Chapter 3, Creating Bar Charts, the Building vertical bar charts recipe, as we will start from those.

How to do it...

The following are the steps needed to animate a bar chart:

  1. In the Bar.as class, add the _onEnterFrame function:
    private function _onEnterFrame(event:Event):void {
      var distance:Number = Math.abs(height - _targetHeight);
      if (distance < 0.1) {
        height = _targetHeight;
        removeEventListener(Event.ENTER_FRAME, _onEnterFrame);
      } else {
        height -= (height - _targetHeight) / 4;
        //the 4 here impacts on the speed of the animation, higher being slower
      }
    }
  2. Always in Bar.as, add the two public functions animateIn and animateOut, as shown in the following code snippet:
    public function animateIn():void {
      _targetHeight = _startingHeight;
      addEventListener(Event.ENTER_FRAME, _onEnterFrame);
    }
    public function animateOut():void {
      _targetHeight = 0;
      addEventListener(Event.ENTER_FRAME, _onEnterFrame);
    }
  3. In BarChart.as, start by setting the alpha variable to 0 in the constructor.
  4. After that, add the animateIn and _onEnterFrame functions:
    public function animateIn():void {
      addEventListener(Event.ENTER_FRAME, _onEnterFrame);
      setTimeout(_animateInBars, 1500);
    }
    
    private function _onEnterFrame(event:Event):void {
      if (alpha > .95) {
        alpha = 1;
        removeEventListener(Event.ENTER_FRAME, _onEnterFrame);
      } else {
        alpha += (1 - alpha) / 8;
        //the 8 here impacts on the speed of the animation, higher being slower
      }
    }
  5. Save references to individual bars in Vector so that you animate them later on.
  6. Add the _animateInBars and _animateOutBars functions:
    private function _animateInBars():void {
      for (var i:int = 0; i < _barVector.length; i++) {
        _barVector[i].animateIn();
      }
    }
    private function _animateOutBars():void {
      for (var i:int = 0; i < _barVector.length; i++) {
        _barVector[i].animateOut();
      }
    }
  7. Create the public function update and its follow up function _continueUpdate:
    public function update(data:Vector.<BarData>):void {
      _data = data;
      _animateOutBars();
      setTimeout(_continueUpdate, 800);
    }
    
    private function _continueUpdate():void {
      var i:int;
      for (i = 0; i < _barVector.length; i++) {
        removeChild(_barVector[i]);
      }
      _barVector = new Vector.<Bar>();
    
      var bar:Bar;
      for (i = 0; i < _data.length; i++) {
        bar = new Bar(_barWidth, _data[i].data * _scaleHeight);
        bar.x = 10 + _barSpacing + _barWidth / 2 + i * (_barWidth + _barSpacing);
        bar.y = _newHeight - 10;
        _barVector.push(bar);
        addChild(bar);
      }
      addChild(_horizontalAxis);
      _animateInBars();
    }
  8. In Main.as, create a second data set called _data2.
  9. After 1.5 seconds, tell _chart to animate in:
    setTimeout(_chart.animateIn, 1500);
  10. After 8.5 seconds, change the data set to see the chart animate:
    setTimeout(_changeData, 8500);
    
    private function _changeData():void {
      _chart.update(_data2);
    }

How it works...

Two tools are going to help us animate the bar chart: the enter frame listener function and the setTimeout function.

By adding a listener to the event ENTER_FRAME, we created a function that will be called every time a new frame is created. By updating a value such as alpha or height towards a target, we create an animation. Both in Bar.as and BarChart.as we use this as a stratagem (see step 1 and step 4).

Now this listener function is divided into two parts. Since we are getting closer to the value that is animated by a fraction, we first need to check if we are close enough to stop (otherwise you keep animating forever and it is not very optimal). If so, we set the value to the target and we stop animating. If not, we calculate the distance left, and we move forward by a fraction of the distance; for example, if we calculate half or a quarter of the distance left, then the smaller the fraction, the slower the animation will play. Eventually, our value is going to be very close to our target and the first condition will trigger.

You could animate differently based on time, instead of based on the distance, but in this way, you could easily get a nice easing, which means that our animation will be fast at first and slow in the end, finishing smoothly.

Another concept of animation is timing/delay. As an example to illustrate this, you may want to play another animation after the first one has played or you would want to play another animation after a certain amount of time. In ActionScript, there is a utility function called setTimeout that lets you do so. It takes two parameters: the first is a function to be called after some time and the second is that said amount of time in milliseconds (1000 millisecond equals to 1 second).

With those tools in hand we can animate the bar chart. The following is the sequence of events. At 1.5 seconds, we fade in the graph (alpha from 0 to 1). At 3 seconds, we animate in all the bars by making their heights go from 0 to their target values. At 8.5 seconds, we tell the chart to switch its data, so it will animate out all the bars and after 0.8 seconds, it will animate in the bars to their new heights.

There's more...

For this recipe we used setTimeout and the enter frame listener function but we could have just used the TweenLite animation library.

Using TweenLite

TweenLite is a very popular animation library that can be used very easily when animating one property, such as in this case the height of the bars. Here, instead of using the animateIn and _onEnterFrame functions, we could have used TweenLite and it would have been one line instead of 10. Another really useful feature of TweenLite is the delayedCall function, which is very similar to setTimeout but uses seconds instead of milliseconds. It's a small advantage, but it helps reduce confusion in the code. We chose to use TweenLite in this book as it is the most used and fastest animation library out there.

See also

  • The Building vertical bar charts recipe in Chapter 3, Creating Bar Charts
  • The Animating a meter recipe
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.129.13.201