Oct 03

This is a very interesting sample suggested by Karthik. He asked if it is possible to reverse an animation created by Storyboard. He provided me a rotating cube created by Swift3D (In the latest version, it supports exporting 3D animation to XAML) and my task is to make it alive.

Besides, the animation speed can be controlled by the mouse movement as well. (Try to drag over the screen.)

Since Storyboard Animation and Timeline Animation are completely different, the approach on reversing the animations differs as well.

Vote for this sample

Flash is Better? (250 votes)
Silverlight is Better! (256 votes)

Comparison

Flash implementation: 40 minutes
Silverlight implementation: 180 minutes (Implemented First)
What’s the difference?

  • Reverse Animation: gotoAndStop [AS3] vs Storyboard.Seek [C#]

Source codes

Flash

Silverlight

Reverse Animation: gotoAndStop [AS3] vs Storyboard.Seek [C#]

By using  gotoAndStop and Timer Class together, it’s not difficult to reverse the animations. Let’s take a look on the sample below.

// AS3

// get the cube animation from the stage
var _cube:MovieClip = getChildByName("cube") as MovieClip;
// animation movement speed
var _speed = 25;
// moving direction: 1 = normal, -1 = reverse
var _sign = -1;

var _timer:Timer = new Timer(_speed);
_timer.addEventListener(TimerEvent.TIMER, on_timer);
_timer.start();	 

private function on_timer(e : TimerEvent):void{
	// get the target frame
	var _currentFrame:int = _cube.currentFrame + _sign;
	if(_currentFrame > _cube.totalFrames){
		_currentFrame = 0;
	}else if(_currentFrame <= 0){
		_currentFrame = _cube.totalFrames;
	}
	// animate the movieclip
	_cube.gotoAndStop(_currentFrame);
}

// change the speed of the animation
_timer.delay = newValue;

However, I got a nightmare in C#. The Seek method simply doesn’t work if you set a position less than the previous value. After many attempts, I got the solution finally.

The code is a little bit strange, but it just work. If you have a better approach, please let me know.

// C#
// start the enter frame event
Dispatcher _timer = new DispatcherTimer();
_timer.Interval = new TimeSpan(0, 0, 0, 0, 40);
_timer.Tick += new EventHandler(_timer_Tick);
_timer.Start();

// Rotation is the Storyboard
Rotation.Begin();
Rotation.Pause();

// Speed
int _speed = 40; // or -40 to make it reverse

// Seek Position
TimeSpan _timeSpan = new TimeSpan();
// Animation length
TimeSpan _maxTimeSpan = new TimeSpan(0, 0, 10);

void _timer_Tick(object sender, EventArgs e)
{
    if (_speed >= 0)
    {
	// Increase the seek position
        _timeSpan += new TimeSpan(0, 0, 0, 0, _speed);

	// if it reached to maximum, set it to 0
	if(_timeSpan.Ticks > _maxTimeSpan.Ticks){
		_timeSpan = new TimeSpan();

        Rotation.Seek(_timeSpan);
    }
    else
    {
	// Decrease the seek position
        _timeSpan -= new TimeSpan(0, 0, 0, 0, Math.Abs(_speed));

        // if it reached to 0, set it to maximum time
        if (_timeSpan.TotalMilliseconds < 0)
            _timeSpan = new TimeSpan(_maxTimeSpan.Ticks);

        // Hacking for reverse
        Rotation.Stop();
        Rotation.Begin();
        Rotation.Seek(_timeSpan);
        Rotation.Pause();
    }
}
Sep 20

By just adding a little more on the Carousel, you can create a brand new Crousel effect. Today, I am presenting you the advanced Carousel Effect which support various layers with additional Drill Down and Drill Up effects.

You can also experience how did I simulate the frame based animation by StoryBoard. A pretty good reference for you to learn Silverlight.

Vote for this sample

Flash is Better? (170 votes)
Silverlight is Better! (240 votes)

Comparison

Flash implementation: 50 minutes
Silverlight implementation: 1 hour (Implemented First)
What’s the difference?

  • Tween [AS3] vs Storyboard [C#]

Source codes

Flash

Silverlight

Tween [AS3] vs Storyboard [C#]

In AS3, the Class fl.transitions.Tween is very similar to StoryBoard in C#. Below is a simple demonstration which fade out an object in 3 seconds.

// AS3
import fl.transitions.*;
import fl.transitions.easing.*;

var storyBoard:Tween = new Tween(displayObject,  "alpha", None.easeOut, 1, 0, 3, true);
storyBoard.addEventListener(TweenEvent.MOTION_FINISH, on_motion_finish);

function on_motion_finish(e:TweenEvent):void{
	trace("finish");
}

What about in C#? let’s see how can we create Storyboard purely by code. Please be careful when using Storyboard.SetTargetProperty, you have to use “(LayoutRoot.Opactiy)” as the argument, don’t miss out the blankets!

There has been many chances on the Storyboard since Silverlight 1. You will find a lot of “wrong” information from the Internet which can not work properly in beta 2.

// C#
Storyboard storyboard = new Storyboard();
DoubleAnimation doubleAnimatoin = new DoubleAnimation();
doubleAnimatoin.From = 1;
doubleAnimatoin.To = 0;
doubleAnimatoin.Duration = new Duration(new TimeSpan(0, 0, 3));
Storyboard.SetTarget(doubleAnimatoin, displayObject);
Storyboard.SetTargetProperty(doubleAnimatoin, new PropertyPath("(LayoutRoot.Opacity)"));

storyboard.Children.Add(doubleAnimatoin);
storyboard.Begin();
Sep 05

This example illustrated the differences in rendering polygon using AS3 and C#. You may also reuse the Class as your drawing library. 

Blog Logo

Today, I have completed the Website Logo. The Logo is inspired from the Chinese Concept “Taiji” (太極).

In the original Taiji Logo, a black (white) dot is inside the white (black). It means that for Chinese people, they think Black and White are not necessary completely separated. Instead, they can exist together.

This concept can be applied to Flash and Silverlight as well. They have their strength and weakness and I believe they can coexist together for solving different problem.

Comparison

Flash implementation: 45 minutes 
Silverlight implementation: 45 minutes 
What’s the difference?

  • Rendering Polygon: beginFill, lineTo [AS3] vs System.Windows.Shape.Polygon [C#]

Source codes

Flash

Silverlight

Rendering Polygon: beginFill, lineTo [AS3] vs System.Windows.Shape.Polygon [C#]

AS3 does not have any native support for rendering polygon. However, it’s quite simple to achieve this using the Graphics Library.

// AS3
// You may add this function to the Class: Shape, Sprite, MovieClip
// for rendering the polygon
public function drawPolygon(corner:int, radius : Number, color : uint = 0, alpha:Number = 1) : void {
	graphics.clear();
	graphics.beginFill(color, alpha);
	graphics.moveTo(radius, 0);

	for(var i:int = 0; i < corner; i++){
		var angle:Number = 2 *  Math.PI/ corner * (i + 1);
		var lineX:Number = Math.cos(angle) * radius;
		var lineY:Number = - Math.sin(angle) * radius;
		graphics.lineTo(lineX, lineY);
	}
	graphics.endFill();
}

In C#, you can use the Polygon Class directly to render any shape you like.

// C#
// create the Polygon
public void addPolygon(int corner, double radius , Color color)  {
	Polygon polygon = new Polygon();
	polygon.Fill = new SolidColorBrush(color);
	for(int i = 0; i < corner; i++){
		double angle = 2 *  Math.PI/ corner * (i + 1);
		double x = Math.Cos(angle) * radius;
		double y = - Math.Sin(angle) * radius;
		polygon.Points.add(new Point(x, y));
	}

	// add the polygon to the stage
	LayoutRoot.Children.Add(polygon);
}

What’s More? DispatcherTimer vs Storyboard in C#

Previously, some people suggest that I may use the Storyboard to render the animations. However, to my understands, it’s not easy to simulate some mathematical calculations (like making spring effect) purely using Storyboard. Anyway, Storyboard can be used as a replacement of DispatcherTimer. But actually I can’t see any difference yet.

The DispacherTimer is a class from the System.Windows.Threading, may be it be used for some multi-threading purpose.

// C#
// Using Storyboard to simulate ENTER FRAME Event
Storyboard storyBoard = new Storyboard();
storyBoard.Duration = TimeSpan.FromMilliseconds(1000 / FPS);
storyBoard.Completed += new EventHandler(storyBoard_Completed);
void storyBoard_Completed(object sender, EventArgs e)
{
	if(conditionToKeepGoing){
		// do something
		_storyBoard.Stop();
	}
}

// Using Storyboard to simulate ENTER FRAME Event
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 0, 0, 1000 / FPS);
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
void _timer_Tick(object sender, EventArgs e)
{
	// do something
	if(not conditionToKeepGoing){
		timer.Stop();
	}
}