Saturday, August 23, 2008

Fade Text Without Embedding a Font

Note to Self: A while back, Amy mentioned a really easy way to do this on Flex Coders: Set the "blendMode" property to "layer" (or BlendMode.LAYER). Another idea is to use the "filters" property to apply a filter to a DisplayObject. Both of these approaches convert the object to a bitmap for you!

Effects like Fade or Rotate won't play nice with text. One way around this is to embed a font in your SWF, but that's just New Bulk City. A coworker reminded me that everything would be hunky-dory if I converted the component to a bit map. Here's an example where I use the ImageSnapshot class to do just that.

I used view states to swap out a Canvas based component with a bitmap image in a SWFLoader. Then I used the SWFLoader's complete event to trigger the final view state, where the Fade effect is actually played.

A little bit of extra work pays off... now the text fades out with the rest of the component. Right click on the app to view the source.

Wednesday, August 20, 2008

Balls, balls, balls!

A prospective employer put forward this little test to screen potential candidates, this is my quick solution. Not quite production ready code, but I don't think they are expecting that for something like this :)

The problem:

Write a Flash application that loads a BML file from an arbitrary URL. A BML file is "ball markup language". It looks something like this:

ball_name:
    color: FF0000
    radius: 40
    appear:
        time: 2
        x: 40
        y: 40
    disappear:
        time: 15
        x: 260
        y: 260

A solution:

My solution was written in Flex, which if you can't tell, I am smitten with. I didn't implement the loading from an arbitrary URL part, but that is trivial using an URLLoader or HTTPService. The code I wrote to parse the BML input is real horror show. But in the real world we'd use XML, JSON, etc. to retrieve this data so I didn't think it was necessary to write something more robust.

I like to write elegant, maintainable code. This is not necessarily the most elegant solution, but it's not bad given that I only spent a few hours doing it. Check out the Ball.as class which does most of the heavy lifting. You can right click on the app to view the source code.

Here is some sample BML markup that you can paste into the app:

brownie_points:
    color: 5B4202
    radius: 30
    appear:
        time: 1
        x: 175
        y: 175
    disappear:
        time: 15
        x: 15
        y: 15
deep_purple:
    color: 380A67
    radius: 35
    appear:
        time: 5
        x: 50
        y: 50
    disappear:
        time: 15
        x: 250
        y: 250
green_monster:
    color:  3F912D
    radius: 99
    appear:
        time: 3
        x: 350
        y: 125
    disappear:
        time: 18
        x: 45
        y: 125
orange_crush:
    color: ECB834
    radius: 77
    appear:
        time: 10
        x: 250
        y: 50
    disappear:
        time: 20
        x: 25
        y: 250

Tuesday, August 19, 2008

Reversing the order of child XML tags

e4x is so powerful, that when I'm working with XML data I'm like Nike: I just do it. It makes everything so easy.

But today I scratched my head for a while on how to achieve a simple task. A BarChart was not rendering my data in descending order. It wasn't the chart's fault, it just rendered the data in the order that the data was being supplied (first item at the bottom). Rather than ask the back end guys to change the order of the XML, I thought I would do a simple reverse() on the data.

Alas, none of the XML, XMLList, or XMLListCollection classes have a reverse() method. That would be a nice enhancement, in my opinion... to be able to reverse the order of an element's child tags.

Here's what I did to get the job done. It's short and sweet, but it took me a few go-rounds to come up w/the solution, so I am documenting it here in case I need it again:


private function reverseChildren( x:XMLList ):XML
{
    var root:XML = <root></root>;
    var children:XMLList = x.children();
   
    for (var i:int = children.length() - 1; i >= 0; i--)
    {
        root.appendChild( children[i] );
    }
   
    return root;
}

This snippet throws away the name of the orginal root tag, but that never seems to matter anyway!

Friday, August 15, 2008

Inverting a Chart Series

You can plot multiple data series on a chart directly on top of each other, or by stacking them. Another way to plot them is by inverting one of the data series so that it is drawn upside down below the horizontal axis.

In the example below I used an AreaChart with two AreaSeries representing the data. You can use the dataFunction property of the series to tell Flex how to render the data. In this case I negated one of the series so it would be drawn below the axis. I also used the labelFunction property of the vertical axis to make sure that labels would be printed with positive values.

Right click on the example below to view the source.