Perspective : MayaEase

Perspective : MayaEase

Features

The MayaEase class of the Perspective for Silverlight library defines a custom interpolation curve for Silverlight 3 animations, which looks like a Maya pyramid :

MayaEase interpolation curve

2 properties are used to configure the interpolation :

  • StepCount : number of levels (4 by default).
  • Threshold : normalized value (between 0 and 1) indicating the level in the threshold relative to its size. The default is 0.2. A value of 0.5 gives the following curve :

MayaEase interpolation curve - threshold 0.5

MayaEase fits well with an animated carousel. In the following example, the carousel is made up of 4 images projected in a 3D perspective. The animation is applied to the RotationX property of the projection. The starting angle of rotation is offset by 90 degrees for each image.

Carousel

<Storyboard 
  x:Name="storyboard"
  RepeatBehavior="Forever"
  >
  <DoubleAnimation
    x:Name="animation1"
    Storyboard.TargetName="image1" 
    Storyboard.TargetProperty="(Image.Projection).(RotationX)" 
    Duration="0:0:20"
    From="0" To="360"/>
  <DoubleAnimation
    x:Name="animation2"
    Storyboard.TargetName="image2" 
    Storyboard.TargetProperty="(Image.Projection).(RotationX)" 
    Duration="0:0:20"
    From="90" To="450"/>
  <DoubleAnimation
    x:Name="animation3"
    Storyboard.TargetName="image3" 
    Storyboard.TargetProperty="(Image.Projection).(RotationX)" 
    Duration="0:0:20"
    From="180" To="540"/>
  <DoubleAnimation
    x:Name="animation4"
    Storyboard.TargetName="image4" 
    Storyboard.TargetProperty="(Image.Projection).(RotationX)" 
    Duration="0:0:20"
    From="270" To="630"/>
</Storyboard>
...
<Image 
  Name="image1"
  Stretch="None" 
  Margin="10"
  Source="http://.../s400/DSC_0832.jpg">
  <Image.Projection>
    <PlaneProjection
      CenterOfRotationZ="-200"/>
  </Image.Projection>
</Image>
...
// C#
private void bMaya2_Click(object sender, RoutedEventArgs e)
{
  MayaEase ease = new MayaEase();
  ease.EasingMode = EasingMode.EaseIn;
  ease.Threshold = 0.5;
  DrawEaseCurvePath(ease);
  StartAnimation(ease);
}
private void StartAnimation(EasingFunctionBase ease)
{
  storyboard.Stop();
  animation1.EasingFunction = ease;
  animation2.EasingFunction = ease;
  animation3.EasingFunction = ease;
  animation4.EasingFunction = ease;
  storyboard.Begin();
}

Demo (Silverlight 3)

Architecture

MayaEase class inherits from EasingFunctionBase and redefines the EaseInCore method. It receives as parameter the time, in a standardized form (value between 0 and 1, representing the duration of the animation). It returns a normalized value (between 0 and 1) that applies to the animated property value. Only EaseIn mode is implemented using this function. EaseOut and EaseInOut modes are determined automatically by the Ease method of the EasingFunctionBase Class.

protected override double EaseInCore(double normalizedTime)
{
  double normalizedTargetValue = 1.0;
  for (int i = 0; i < StepCount; i++)
  {
    double stepStart = (double)i / StepCount;
    double stepLength = 1.0 / StepCount;
    double thresholdStart = stepStart + Threshold * stepLength;
    double stepEnd = stepStart + stepLength;
    if ((normalizedTime >= stepStart) && (normalizedTime < thresholdStart))
    {
      normalizedTargetValue = stepStart + (normalizedTime - stepStart) / Threshold;
      break;
    }
    if ((normalizedTime >= thresholdStart) && (normalizedTime < stepEnd))
    {
      normalizedTargetValue = stepEnd;
      break;
    }
  }
  return normalizedTargetValue;
}

About this article

Author : Olivier Dewit.

History :