Basic Graphics and Animation in Flex

One thing I’ve been spending a lot of time with these days is the Visualization SDK. The MicroStrategy samples primarily talk about wiring MicroStrategy controls in your visualizations. While those make good tutorials, it seems to me that if you wanted to use MicroStrategy controls, you wouldn’t need to use the Visualization SDK. For me, I go to Flex when I need to build something completely custom from scratch.

I’m primarily a MicroStrategy Architect/Developer and by no means a professional Flex programmer. All of the information I have to share I’ve figured out on my own or gleamed from countless Google searches. Here is the first of hopefully many posts that comprise various Flex tips for a non-Flex programmer. Some programming background is going to be required, and any experience with Java will be a big plus. I’m not going to provide super detailed steps, but hopefully enough to get you in the right direction. I’ve built some pretty amazing looking visualizations that I can’t share yet, and it was a lot easier than I expected. Give it a try!

Flex is made up of two parts: XML for layout, and ActionScript for code. You don’t need both and can write a widget completely using one or the other. MicroStrategy samples primarily use XML to layout the controls, but I very rarely do. I do all of the graphics by hand, and that’s what I’ll cover today.

DrawingYou can actually draw on just about anything. You can draw directly on your control, but I prefer to draw on a Canvas object. This will come in handy when your control gets more complicated and you want to handle dynamic resizing.

You can also draw on a Sprite object which gives you a little bit more control over separating out your graphics. For example, if you want to add a Click Event to a particular piece of graphic, you’ll need it to be a separate object and a Sprite can come in handy for that.

Drawing on all of them is the same code. Here’s a sample:var canvas:Canvas = new Canvas();canvas.graphics.lineStyle(thickness, 0x000000, alpha);canvas.graphics.beginFill(0x000000,alpha);canvas.graphics.moveTo(x,y);canvas.graphics.lineTo(x+10, y+10);canvas.graphics.lineTo(x+10, y);canvas.graphics.lineTo(x,y);addChild(canvas);

The above code will draw a triangle on the screen.

Some notes:

lineStyle and beginFill are declarations for the graphics you’re about to perform. If you’re going to do lots of drawing, here is where you would want to draw on Sprites and add them to your canvas or control. The reason is because juggling changing lineStyle and beginFill‘s can be a real mess, whereas encapsulating them in a Sprite makes things easier to manage. thickness is an integer value for the number of pixels in width for the line. alpha is a floating point value for the percentage of transparency, where 1 is solid and 0 is invisible.

moveTo sets up your starting point, and lineTo draws a line to the new point. The x,y coordinate system starts where 0,0 is the first pixel in the top left corner. There are other options such as curveTo if you want to get really fancy. Instead of moveTo / lineTo, you can also also use drawCircle and drawRect to draw basic shapes instead of lines, but if you do go with lines and want to fill it, don’t forget to draw back to the starting point to get a proper fill.

Once you’re done, you can add the canvas object to your control by doing addChild(canvas). If you chose to draw on a Sprite, a Sprite can’t be directly added to a container unless you add rawChildren.addChild(Sprite).

Animate ItNow that you are a drawing professional, animation is actually really easy as well.

For this example, I’ll use a Sprite (since I didn’t in the previous but talked about it a lot). So say you’re drawing a bar graph:var graph:Sprite = new Sprite();graph.graphics.lineStyle(1, 0x000000, 1);graph.graphics.beginFill(0x000000, 1);graph.graphics.drawRect(100,100,50,100);drawRect takes the parameters (x,y,width,height)

While that would draw a rectangle like we did in the first example, let’s animate it. Instead of the above code, do the following:var graph:Sprite = new Sprite();graph.addEventListerner(Event.ENTER_FRAME, doEveryFrame);rawChildren.addChild(graph);This event listener will automatically call the function doEveryFrame every time a frame is drawn on the control. You can set the frame rate with the following line, which should be done right at the beginning of your code:stage.frameRate = 30;Which frame rate you use doesn’t really matter, but you should set one. You should also set a few constants up at the top of your control between the import statements and your first function:private var currentFrameCount:Number = 0;private var SecondsToAnimate:Number = 3;

currentFrameCount will be how we keep track of progress, and SecondToAnimate is just a constant so you can control how long you want your animation to take.

So, your doEveryFrame function may look something like this:private function doEveryFrame(evt:Event):void {var pct:Number = currentFrameCount / (stage.frameRate*SecondsToAnimate); if (pct <= 1) { evt.target.graphics.clear(); evt.target.graphics.lineStyle(1, 0x000000, 1); evt.target.graphics.beginFill(0x000000, 1); evt.target.graphics.drawRect(100,100,50,100*pct); currentFrameCount++; } else { evt.target.removeEventListener(Event.ENTER_FRAME, doEveryFrame); }}So the basic idea is to measure the Percentage of the progress. Progress is measured by dividing the currentFrameCount by the total number of frames we need to animate, which is the frameRate * SecondsToAnimate. If we haven’t reached 100% yet, then clear the graphics and draw a rectangle, but the key is to only draw the height a percentage of the way to the maximum, which is why we multiply the height by pct. evt is the variable coming in from the Event that fired, and target is what fired it. So evt.target references the graph Sprite from above where we are drawing on. Once we reach 100% (pct > 1) we should remove the EventListerner, otherwise it will keep going forever.

That’s it! If you put this code all together and run it, you should see a 50×100 rectangle grow to full height over the course of 3 seconds. Pretty easy?