Sunday, August 8, 2010

Animating the perspective projection of a DisplayObject

So as you probably know, in flex 3 we could animate objects only by their numerical properties. Which for most situations is enough, like positioning or resizing component. But sometimes you will want to animate a complex object, and in flex 4 that is possible using arbitrary type interpolation. You can see this great demo on the topic on adobe tv by Chet Haase. Mine example isn't nothing more special than his, I just decided to do it because I saw few people entering my blog wanting to see an example of using perspective projection other than in my previous post - custom flex 4 layout and because recently I had to do similar animation, but I have done it the "dirty" way (yeah I admit it), so I thought it is time to correct it.



The most important thing is our PPInterpolator and its method interpolate()

public function interpolate(fraction:Number, startValue:Object, endValue:Object):Object
{
    var startPP:PerspectiveProjection = startValue as PerspectiveProjection;
    var endPP:PerspectiveProjection = endValue as PerspectiveProjection;
    
    var currentPP:PerspectiveProjection = new PerspectiveProjection();
    currentPP.fieldOfView = startPP.fieldOfView + fraction * (endPP.fieldOfView - startPP.fieldOfView);
    currentPP.focalLength = startPP.focalLength + fraction * (endPP.focalLength - startPP.focalLength);
    
    var projectionCenterX:Number = startPP.projectionCenter.x + fraction * (endPP.projectionCenter.x - startPP.projectionCenter.x);
    var projectionCenterY:Number = startPP.projectionCenter.y + fraction * (endPP.projectionCenter.y - startPP.projectionCenter.y);
    
    currentPP.projectionCenter = new Point(projectionCenterX, projectionCenterY);
    
    return currentPP;
}

You see that we expect startValue and endValue to be instances of PerspectiveProjection and return a new instance based on these values as a value for the current moment of the animation.

The other thing is as just writing a normal animation, we are just setting the interpolator of the motion path to be the one we created and set the target of the animation the transform property of a group (it could be any other DisplayObject). Have a look at the valueFrom and valueTo, we are passing instances of PespectiveProjection

<fx:Declarations>
    <effects:PPInterpolator id="ppInterpolator"/>
    
    <s:Animate id="ppAnimate" target="{group.transform}" duration="3000" >
        <s:motionPaths>
            <fx:Script>
                <![CDATA[
                    import com.tgeorgiev.effects.PPInterpolator;
                ]]>
            </fx:Script>
            <s:SimpleMotionPath property="perspectiveProjection" valueFrom="{startPP}" valueTo="{endPP}" interpolator="{ppInterpolator}" />
        </s:motionPaths>
    </s:Animate>
</fx:Declarations>

The group that is the target of the animation just holds 3 images with different rotations and positions.

That's all, I suggest you play with the random animate button, for fun :)

No comments:

Post a Comment