The fundamental idea behind a tag cloud is to display, at a glance, which tags (categories) are the most popular ones. This is done by varying the presentation of each tag to reflect its popularity - usually by showing more popular tags in a bigger font size.
Now this whole folksonomy thing can get fairly complicated, and I found various examples of fairly complex algorithms to calculate the font size distribution. I didn't want to jump in at the deep end though, so I decided to just go with my gut and implement something simple that I thought would do the trick.
Assuming that we have a table that maps a given tag to a given blog post (or whatever resource is being tagged), a simple SQL query can tell us the popularity values:
When we have that, we need to figure out which tags gets which font size. Lets assume that we want to group the tags into noOfWeightGroups different font sizes. First, we need to know the minimum and maximum popularity values, which is easy enough to figure out. With that, we can calculate the popularity bounds that decide what goes where, so that f.ex tags with a popularity rating between 0 and 5 goes into group 1, 6-10 goes into group 2 and so forth.
This is then the meat of our algorithm:
int groupSize = (int)Math.Round( (double)(maximumPopularity - minimumPopularity) / noOfWeightGroups);
if (groupSize == 0)
{
groupSize = 1; // if groupsize is 0 (ie all tags equal popularity), then we'd go into an infinite loop later...
}
foreach (Tag tag in tags)
{
tag.Weight = (tag.Popularity / groupSize) - minimumPopularity + 1;
if (tag.Weight > noOfWeightGroups)
{
tag.Weight = noOfWeightGroups;
}
}
Each tag now has a weight, which is a value indicating the group it belongs to. When we display the tags, we can then use that value to decide on which style to use for the links:
<asp:HyperLink
ID="_tagLink"
runat="server"
Text='<%# Bind("Name") %>'
NavigateUrl='<%# Bind("Link") %>'
CssClass='<%# Bind("Weight", "Tag_{0}") %>'
ToolTip='<%# Bind("Popularity", "There are {0} posts tagged with this tag.") %>' />
Assuming we then have defined css classes Tag_1 through Tag_6, we'll get a nicely distributed tag cloud :)