Blog

Back to Blog

Animating ShinobiChart Series

Posted on 14 Mar 2013 Written by Dan Allsop

With the release of ShinobiCharts 2.2.0 just around the corner now seems like the perfect opportunity to shine the spotlight on one of the new features… Animations! This blog post describes how to use the built in animations that ShinobiCharts provides, how to customise them and even create you own.

For those readers who haven’t experienced the animations, they are essentially another feature that ShinobiCharts provides enabling you to display your data in increasingly impressive ways. This is achieved by providing a more visually stimulating way of hiding and revealing the series in your ShinobiCharts. In this blog I will be using the ShinobiCharts Framework to add animations to the series in the Line Chart Demo that comes bundled as part of our free trial download.  No framework? Then just go ahead and download a trial version here, and let’s get started!

 

Enabling Animations

The first step is to enable the animations on your series by setting the animationsEnabled property which can be done when you create the series, as shown in the following example:

series.animationEnabled = YES;
series.animationEnabled = NO;

 When setting animationEnabled to YES on a series it will cause the series to enter and exit with an animation when the SChartSeries hidden property is toggled. Animations are available for all series types and when enabled cause the default animation for that series to be used. Enabling animations has the benefit of allowing the series to disappear and reappear using smooth transitions, instead of instantaneously, which is the default behaviour.

 

Choosing Different Animations

The next step after enabling animations is to customise them. 

By default each of the series types entry and exit animations are set to one of the following preset animations: fadeAnimation, growAnimation, growHorizontalAnimation, growVerticalAnimation, televisionAnimation and radialSelection with some series such as SChartColumnSeries and SChartCandlestickSeries being set to growVerticalAnimation by default, and others such as SChartLineSeries and SChartBandSeries set to televisionAnimation by default, as shown in the table below:

  televisionAnimation growVerticalAnimation growHorizontalAnimation growAnimation
LineSeries X      
StepLineSeries X      
BandSeries X      
ColumnSeries   X    
OHLCSeries   X    
CandlestickSeries   X    
BarSeries     X  
ScatterSeries       X
DonutSeries       X
PieSeries       X

 

However the animations can be changed from the series default to any of the available preset animations. The animations can also have their durations changed in the following way:

SChartAnimation *animation = [SChartAnimation fadeAnimation];
animation.duration = @3;

 These animations can be assigned to your series of choice as either its entry or exit animation. Remember to avoid setting the same instance of SChartAnimation to both the entry and exit animation as this will not work. This is because the entry and exit animations will be setting the properties on the same animation instance if they are they are referencing the same object. The entry and exit animations of a series are set as follows:

series.entryAnimation = animation;
series.exitAnimation = [animation copy];

In addition to the above you can also change the position from where the series will start animating for entry animations, and the position the series will animate to for exit animations by setting the following properties on the series:

series.entryAnimation.absoluteOriginX = @0;
series.entryAnimation.absoluteOriginY = @0;

or

series.entryAnimation.normalisedOriginX = 0.f;
series.entryAnimation.normalisedOriginY = 0.f;

The difference between those two sets of properties is that absoluteOrigin uses the exact data values on the axis as a guide for where to move the series from/to, whereas normalisedOrigin creates a mapping between the values 0 to 1 and the values in your data range, with 0 being equal to he smallest value in your data range and 1 being the largest value in your data range. If both absoluteOrigin and normalisedOrigin are set then the absoluteOrigin takes precedence.

 

Custom Animations 

But that’s not all! 

The more ambitious among you might want to go a step further and create fully customised animations. SChartAnimation has multiple properties, each of type SChartAnimationCurve, as described below:

  • curve sets all of the other animation curves to this curve.
  • xScaleCurve sets the animation curve describing the transition of the series parallel to the xAxis.
  • yScaleCurve sets the animation curve describing the transition of the series parallel to the yAxis.
  • angleCurve sets the animation curve describing the transition of the series around the origin of the radial series.
  • radiusCurve sets the animation curve describing how the radius/radii of the series change during the animation.
  • alphaCurve sets the animation curve describing how the transparency of the series changes during the animation.

These curves can be set to any of the following SChartAnimationCurve types:

  • SChartLinearAnimationCurve
  • SChartEaseInAnimationCurve
  • SChartEaseOutAnimationCurve
  • SChartEaseInOutAnimationCurve
  • SChartBounceAnimationCurve

In the following way:

animation.curve = [SChartBounceAnimationCurve new];

Or you can make your own custom SChartAnimationCurve by creating your own class that implements the SChartAnimationCurve protocol. This will have to implement two methods, the first is valueAtTime: and the second is copyWithZone:.

The valueAtTime: method receives a float time which is a normalised time value between 0 and 1, that is equal to the elapsed time divided by the duration of the animation. The method is expected to return a float, but isn’t expected to return a value between 0 and 1. The following example valueAtTime: method implementation will produce an animation that happens over a constant time period i.e. doesn’t accelerate or decelerate:

-(float)valueAtTime:(float)time{

    return time;

}

A more complicated valueAtTime: implementation would look something like this: 

-(float)valueAtTime:(float)time{

    return sqrt(time);

} 

For an entry animation this will cause the series to begin moving quickly but gradually slow down as it gets closer to finishing, and for exit animation it will have the opposite effect making the series begin moving slowly at first but gradually get quicker as it gets closer to finishing.

For the copyWithZone: method implementation it is sufficient to just make it return a new instance of your custom SChartAnimationCurve class like so because it is stateless:

- (id)copyWithZone:(NSZone *)zone{

    return [[MyCustomSChartAnimationCurve alloc] init];

}

Having implemented both of the above required methods in your custom SChartAnimationCurve class it should look this:

MyCustomSChartAnimationCurve.h file:

 #import <Foundation/Foundation.h>

#import <ShinobiCharts/SChartAnimationCurve.h>


@interface MyCustomSChartAnimationCurve : NSObject <SChartAnimationCurve>

@end

 

MyCustomSChartAnimationCurve.m file:

#import "MyCustomSChartAnimationCurve.h"

@implementation MyCustomSChartAnimationCurve

 -(float)valueAtTime:(float)time{

    return time;

}

- (id)copyWithZone:(NSZone *)zone{   

    return [[MyCustomSChartAnimationCurve alloc] init];

}

@end

 

You should then be able to set the curve properties of SChartAnimation as follows:

MyCustomAnimationCurve myCustomAnimationCurve = [[myCustomAnimationCurve init] alloc];
animation.setXScaleCurve = myCustomAnimationCurve;
animation.setYScaleCurve = myCustomAnimationCurve;
animation.setAngleCurve = myCustomAnimationCurve;
animation.setRadiusCurve = myCustomAnimationCurve;
animation.setAlphaCurve = myCustomAnimationCurve; 

 

Notes for MonoTouch Users

As usual with ShinobiControls, the MonoTouch API is a direct parallel to the native one, with some name changing, particularly in those looooong Objective C selector names. One thing you have to be aware of though is that naming collision rules are different and that MonoTouch exposes native protocols as abstract base classes. So the native SChartAnimationCurve is used as both a protocol and an enum, but in the MonoTouch bindings we have:

public enum SChartAnimationCurve

and

public abstract class SChartAnimationCurveProtocol

When you create your own animation curves you subclass SChartAnimationCurveProtocol:

using System;


using ShinobiCharts;



namespace LineChartSample

{
    

     public class MyAnimationCurve : SChartAnimationCurveProtocol
     
{

     
          public MyAnimationCurve ()
     
     {
        
          }

       

          public override float ValueAtTime(float time)
          
{
            
               return (float)Math.Sqrt(time);
        
          }

        

          public override SChartAnimationCurveProtocol Copy()
          
{
           
               return new MyAnimationCurve ();
        
          }
   
     }

}

setting the SChartAnimation properties as follows:

lineSeries.EntryAnimation = new SChartAnimation () {
    
     XScaleCurve = new MyAnimationCurve (),
    
Duration = new NSNumber(3.0F)

};

lineSeries.AnimationEnabled = true;

 

Summing It Up

Hopefully you now have a better idea about how to go about adding animations to your series, whether by enabling the default animation to give your charts more visual flare, or by going one step further and creating your own animations (which will surely impress your users!). Download the free trial here and have a go yourself!

Back to Blog