In this tutorial I’ll show you how to build a flexible, animatable tagcloud using an Object Oriented Programming approach. I don’t believe in a right or wrong method, but rather several degrees of efficiency. If you have any constructive criticism on my code feel free to comment.
That said, lets start!
Step 1: How to Think Cloud
This step is the most important one as it will dictate all the following steps. I start by looking at what I want to achieve and then break it into pieces, here’s my line of thought:
I want to be able to add multiple tag clouds in a page. I want it to be simple and customizable. So what do I need to build this tag cloud?
I need a word array, a color, a font, minimum and maximum size definitions, oh and I need tag cloud elements to store that information, these elements should be textField based. Since I want several clouds the obvious choice is to create an instanceable tagCloud class that in this case will extend a Sprite.
Here’s what my main function should look like:
var tagCloud:TagCloud = new TagCloud(words,font,color,minFontsize,maxFontsize,fullsize)
As you can tell there are plenty of parameters which need to be defined, the following will walk you trough the process. Create the following files:
- MainTagCloud.fla – this file will instantiate the tagcloud
- TagCloud.as – this is the class that will create the tagcloud
- TagCloudElement.as – this is the element that will populate the tagcloud

Step 2: Building the Mother Class
Open TagCloud.as and write this code
package
{
public class TagCloud extends Sprite
{
public function TagCloud($word_array:Array,$font="Arial",$minFontSize:Number=10,$maxFontSize:Number=30,$elementColor:Number=0xffffff,$fullsize:Number=200):void
{
//here I assign the variables I receive to the class's variables
wordArray = $word_array;
font = $font
minFontSize = $minFontSize
maxFontSize = $maxFontSize
elementColor = $elementColor
fullsize = $fullsize
//after setting the variables I build the cloud
buildTagCloud();
}
}
import these libraries:
import flash.text.Font; import TagCloudElement; // I'll get to this one later on import flash.display.Sprite; import flash.events.Event;
define these variables:
public var cloudElements:Array;
private var wordArray:Array;
private var word:String;
private var relevancy:Number;
private var size:int;
private var element:TagCloudElement;
private var minFontSize:Number;
private var maxFontSize:Number;
private var elementColor:Number;
private var font:String;
private var wordLength:int
private var fullsize:Number
You’ll end up with something like this:
package
{
//First import these packages:
import flash.text.Font;
import TagCloudElement; // I'll get to this one later on
import flash.display.Sprite;
import flash.events.Event;
//Create a class that will extend a sprite
public class TagCloud extends Sprite
{
//we need these variables to be abble to create the tagCloud
public var cloudElements:Array;
private var wordArray:Array;
private var word:String;
private var relevancy:Number;
private var size:int;
private var element:TagCloudElement;
private var minFontSize:Number;
private var maxFontSize:Number;
private var elementColor:Number;
private var font:String;
private var wordLength:int
private var fullsize:Number
public function TagCloud($word_array:Array,$font="Arial",$minFontSize:Number=10,$maxFontSize:Number=30,$elementColor:Number=0xffffff,$fullsize:Number=200):void
{
//here I assign the variables I receive to the class's variables
wordArray = $word_array;
font = $font
minFontSize = $minFontSize
maxFontSize = $maxFontSize
elementColor = $elementColor
fullsize = $fullsize
//after setting the variables i build the cloud
buildTagCloud();
}
}
}
Step 3: Construct Your Main Function
Here’s the main function that will build our cloud.
private function buildTagCloud() {
//create an element array
cloudElements = new Array();
//gets the words lenght so i can iterate trought them and create the elements
wordLength = getSingleWordList(wordArray).length
for (var i=0; i<wordLength; i++) {
//this function returns me an array, its basically a filter, read more about it later on
word = getSingleWordList(wordArray)[i]
//this function uses the wikipedia formula to calculate the element size
size = setElementSize(word, wordArray, minFontSize, maxFontSize);
//creates a new element
element = new TagCloudElement(word, size, font, elementColor);
//stores the new element in the array
cloudElements[i] = element
//sets the transparency based on the size
cloudElements[i].alpha=size/maxFontSize
//just a random way to display the cloud elements
cloudElements[i].x = Math.random() * fullsize
cloudElements[i].y = Math.random() * fullsize
addChild(cloudElements[i]);
//performs a hit test trought the created objects
cloudHitTest(i)
}
}
Step 4: Adding a Word Counter
Let’s see how many words we’re dealing with.
private function countWord($word:String,$array:Array):int {
var count:int=0;
for (var i:int=0; i<$array.length; i++) {
if ($array[i].toLowerCase()==$word.toLowerCase()) {
count+=1;
}
}
return (count);
}
Step 5: Set the Element Size
I set the element size by using a formula found on wikipedia:
function setElementSize($word:String, $array:Array, $minSize:Number, $maxSize:Number):Number {
var $size:Number = $maxSize * countWord($word, $array) / $array.length
$size *= $minSize
return $size
}
Step 6: Creating a Single Word List
This calls a filter for the array.
private function getSingleWordList($source:Array):Array {
var $array:Array=$source.filter(singleWordFilter);
return $array;
}
Now set the filter rules.
private function singleWordFilter(element:*, index:int, arr:Array):Boolean {
if(arr[index+1]){
if (arr[index].toLowerCase()!=arr[index+1].toLowerCase()) {
return true;
} else {
return false;
}
}else {
return false;
}
}
Step 7: How to HitTest
We’re going to need to test for overlapping positions.
private function cloudHitTest($i) {
for (var a:int=0; a < $i; a++) {
//if HITS
if (cloudElements[a].hitTestObject(cloudElements[$i])) {
//Reposition
cloudElements[$i].x = Math.random() * fullsize
cloudElements[$i].y = Math.random() * fullsize
addChild(cloudElements[$i]);
//and test again
cloudHitTest($i)
}
}
}
Step 8: Setting up an Element Getter
This is just a getter of an element by name, in case I need one over the main timeline.
public function getElementByName($name:String):TagCloudElement {
var $auxCloudElement:TagCloudElement;
for (var i:int=0; i < wordLength; i++) {
if (cloudElements[i].word == $name) {
$auxCloudElement = cloudElements[i]
}
}
return $auxCloudElement
}
Step 9: Inside the Element Class
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.Font;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFieldAutoSize;
import flash.text.AntiAliasType;
import flash.text.GridFitType;
import flash.net.URLRequest;
import flash.net.navigateToURL;
public class TagCloudElement extends Sprite
{
public var word:String;
public var urlpath:String;
private var textCloudFormat:TextFormat;
private var textCloud:TextField;
public var font:String;
public var size:Number;
public var color:Number;
// Same constructor as TagCloud, the element extends a Sprite
// and Builds the Element based on a TextField
public function TagCloudElement($word:String, $size:Number = 10, $font:String = "Arial", $elementColor:Number = 0xffffff):void
{
word = $word
font = $font
size = $size
color = $elementColor
buildElement();
}
private function buildElement() {
//creates the textformat
textCloudFormat = new TextFormat();
// defines the font size and color
textCloudFormat.font = font
textCloudFormat.size = size
textCloudFormat.color = color
// creates a textField
textCloud = new TextField();
// embeds the font
textCloud.embedFonts=true;
//sets the antialias to readable equivalent
textCloud.antiAliasType=AntiAliasType.ADVANCED;
//defines its text
textCloud.text=word
//defines its size as automatic
textCloud.autoSize=TextFieldAutoSize.LEFT;
//fit to pixel
textCloud.gridFitType = GridFitType.PIXEL
// unselectable text
textCloud.selectable = false;
// assigns the textformat to the textfield
textCloud.setTextFormat(textCloudFormat)
// adds the MouseEvents listeners
textCloud.addEventListener(MouseEvent.ROLL_OVER,rollOverCloudElement)
textCloud.addEventListener(MouseEvent.ROLL_OUT,rollOutCloudElement)
textCloud.addEventListener(MouseEvent.CLICK,clickCloudElement)
addChild(textCloud);
}
private function rollOverCloudElement(e:MouseEvent){
e.target.textColor = 0x666666;
}
private function rollOutCloudElement(e:MouseEvent){
e.target.textColor = color
}
// I've made a link to a twitter search using the word selected.
private function clickCloudElement(e:MouseEvent){
navigateToURL(new URLRequest("http://search.twitter.com/search?q="+e.target.text),"_blank");
}
}
}
Step 10: Implementation
Now, all that's left to be done is to implement this class in a real .fla file with all the stuff that you are accustumed to (ie:timeline) :P
You'll need to create a font so you can display the textFields, I embeded an Arial font.

Then in the first frame of your .fla import the TagCloud class, set a stage.align to the top left (so that we can find the stage middle position without much work) and create a new instance of the font we just added to the library:
import TagCloud;
stage.align = StageAlign.TOP_LEFT
var wordArray:Array;
var tagCloud:TagCloud;
var arial:Arial = new Arial();//sets a new instance of Arial (already in the library)
function init() {
//creates an array to populate the cloud
wordArray = new Array("In","this","fashion,","text","clouds","may","become","a","generally","applied","tool","for","managing","growing","information","overload","by","using","automated","synthesis","and","summarization","In","the","information","saturated","future","or","the","information","saturated","present");
//sorts the array alphabetically so i can filter later on
wordArray.sort();
// creates a new tagCloud instance
tagCloud = new TagCloud(wordArray,arial.fontName,15,20,0x000000);
// center's it to stage
tagCloud.x = stage.stageWidth*0.5-tagCloud.width*0.5
tagCloud.y = stage.stageHeight*0.5-tagCloud.height*0.5
//adds to stage
addChild(tagCloud);
}
init();
Step 11: Build an RSS Feed Request
Now we need to grab a feed from somewhere so we can cloud it. I chose the CNN news feed. To be able to load an XML you need 4 objects including a urlRequest that will be used as a path to the feed.
var requestFeed:URLRequest = new URLRequest("http://rss.cnn.com/rss/cnn_world.rss");
//an urlLoader so that we can load the request we need to make
var loaderFeed:URLLoader = new URLLoader()
// a XML object so we can store the data we recieve from the feed
var xmlFeed:XML;
//and last but not least a title array that i can explode the words from...
var titleWords:Array;
Step 12: The Initialization Method
Now inside our main function I need to add the complete event handler to the request so that it can be called upon a successful load.
function init() {
loaderFeed.addEventListener(Event.COMPLETE,onFeedComplete)
//I will need the wordArray to be instantiated so I can store the words inside the feed
wordArray = new Array()
//we are ready to load the XML now
loaderFeed.load(requestFeed);
}
Step 13: The Data Structure
The data structure is stored inside the e.target.data so we create the XML here by doing:
function onFeedComplete(e:Event){
xmlFeed = new XML(e.target.data)
//after viewing the source of the rss feed I noticed the structure was something like channel.item.title so i'm using the titles as my word source.
//I need to make an array to store all the words of a title and then add each on of those words inside the word array
//for this I cycle through them
for(var i:uint=0;i<xmlFeed.channel.item.length();i++){
Step 14: Building the Word List
Instanciate the titleWords in every iteration so that you have a clean array everytime we have a new title.
titleWords = new Array()
//to make single words I split them on "space"
titleWords = xmlFeed.channel.item[i].title.split(" ")
//after them being split i iterate them to be added to the wordArray
for(var j:uint=0;j<titleWords.length;j++){
//i use lowercase so i don't have any duplicated words
wordArray.push(titleWords[j].toLowerCase());
}
}
//after that being done I sort the word array alphabetically
wordArray.sort();
//and I start the tagCloud
startTagCloud();
Step 15: Starting the Tag Cloud
Now we have all the elements we need to make this tag cloud.
try{
tagCloud = new TagCloud(wordArray,arial.fontName,20,40,0xFFFFCD,300);
}catch(e:Error){
startTagCloud()
}
//all that is left is to define an X and a Y
tagCloud.x = stage.stageWidth*0.5-tagCloud.width*0.5
tagCloud.y = stage.stageHeight*0.5-tagCloud.height*0.5
//and adding it to the stage
addChild(tagCloud);
//tadaaa we are done..
}
//don't forget to initialize the main function :)
init();
Step 16: The Final Code
Here's the complete code for you to read fully.
import TagCloud;
stage.align = StageAlign.TOP_LEFT
var wordArray:Array;
var tagCloud:TagCloud;
var arial:Arial = new Arial();
var requestFeed:URLRequest = new URLRequest("http://rss.cnn.com/rss/cnn_world.rss");
var loaderFeed:URLLoader = new URLLoader()
var xmlFeed:XML;
var titleWords:Array;
function init() {
loaderFeed.addEventListener(Event.COMPLETE,onFeedComplete)
wordArray = new Array()
loaderFeed.load(requestFeed);
}
function onFeedComplete(e:Event){
xmlFeed = new XML(e.target.data)
for(var i:uint=0;i<xmlFeed.channel.item.length();i++){
titleWords = new Array()
titleWords = xmlFeed.channel.item[i].title.split(" ")
for(var j:uint=0;j<titleWords.length;j++){
wordArray.push(titleWords[j].toLowerCase());
}
}
wordArray.sort();
startTagCloud();
}
function startTagCloud(){
try{
tagCloud = new TagCloud(wordArray,arial.fontName,20,40,0xFFFFCD,300);
}catch(e:Error){
startTagCloud()
}
tagCloud.x = stage.stageWidth*0.5-tagCloud.width*0.5
tagCloud.y = stage.stageHeight*0.5-tagCloud.height*0.5
addChild(tagCloud);
}
init();
Conclusion
I could have used linked lists and while loops to make this a bit faster, but you'll find it reasonably quick. One final note: be sure to set the random size big enough or you'll get a stackOverFlow error when the cloudElement can't find a place to be put.
I hope you liked this tutorial, thanks for reading!




XML Photography Template V2 only $40.00 
Nice
Bruno definitely this is an excellent tut. Nice code.
Great tut.
Very good. Thanks
Great work :)
very nice, very well coded man, thanks a lot for this tutorial
hi, i have problem with open .fla file. I have CS3. Can you save it for my version and send it? Thank you very much
Here you go,
it will only exist for the next 24h or 20downloads…
http://tiny.cc/upJyp
Thanks Bruno,
I grabbed a copy and included it in the existing source.zip. CS3 is therefore now available from the source link at the top of the page.
Thanks Ian
nice tutorial!
There is a WordPress TagCloud worth looking at http://www.roytanck.com/tag/wp-cumulus/
Flash source files are in the Development version
http://wordpress.org/extend/plugins/wp-cumulus/download/
OOP always fries my brain but you did a great job. Thanks!
Maravilhoso, muito bom
hey,
first of all i appreciate your tutorial.
but i have the problem that the source files only work for
your tag cloud example with predefined “words” in your tagCloud.
if i edit the main with the new code, or generate it completly new
with your tutoial i get an error “only expected 5 arguments” referring
to your constructor for your tagCloud, but which you want to initalize
witz 6 arguments:
[...]
tagCloud = new TagCloud(wordArray,arial.fontName,20,40,0xFFFFCD,300);
[...]
even if i fix this (reducing it to the 5 arguments it won’t load or work
with the xml file from cnn.rss or any other.
i would appreciate your help, or instead see the complete source file with
the coude from this tutorial and not with the example without the url loader.
thanks in advance.
greetz.
Sorry, for only reading your question now. Use mainTagCloud_cs3.fla version inside, as it has the xml loader instead of the other fla that has a static name array.
remember, you can’t test the swf in your local machine, because we are accessing http we can only work within a network sandbox. meaning if you want to run inside your computer you need to either host a server in your machine, or edit your flash player security settings.
Cheers
i found bag! Because i don’see last word in array
awesome tutorial! I like that you go from scratch in your code, really helps to walk through the process. Thanks!
hai i am clearning flash current send me some samples of AS2 in flash.That will help me for the future
Hi, I have problem with the.fla file.
I’m currently using CS3. Can you save it in CS3 format and send it again?
Thanks. It’s a good tutorial.
Great tutorial! It save my nerve !
Super tutorial. So easy and clear. Saved me plenty of time.Thank u
Good tut, i like the hitTest method. But it suffers from an issue I have had before. What if it caunt find a place to add an element and you get a “Stack overflow occurred.”
What I do is count the number of times the for loop occurs. If its tried to add it say… 50 times and fails I “break” the for statement and just let it place the element where ever.
Thanks very much, i have been squeezing my brain for two days and many loops/hittests and didnt get a proper way to do it randomly. Your app helped me a lot
Hi!
First of all, this is a very nice tutorial. Thank you!
Now to my problem:
How can I add a hand cursor on mouseover the titles? My words are from an XML-File.
I think I would have to dynamically create MovieClips with “useHandCursor” and “buttonMode” and assign (and placing them above) them to the Arrays which are holding the words?
Any help would be highly appreciated!
Thanks!
Nice, very comprehensive tutorial. However, I have a question, how difficult would be to make it to rotate, like the WP cumulus plugin or like this Flash tag cloud: http://www.flashxml.net/tag-cloud.html ?