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!



Pingback: Down the Foxhole – Last Week on FlashTuts+
Pingback: Adobe Flash: 35+ Animated Trainings | oOrch Blog
Pingback: Twitted by seacloud9
Pingback: 45+ Advanced Adobe Flash Actionscript Trainings | Master Design
Pingback: Advanced Adobe Flash Actionscript Trainings « Flash Criminals
Pingback: Free I Share 分享资源 分享快乐 » Blog Archive » 45个高级Flash Actionscript应用
Pingback: 45+ Advanced Tutorials of Adobe Flash ActionScript « CSS Tips
Pingback: 45+ Advanced Tutorials of Adobe Flash ActionScript | JS Tips