Tuesday, 8 July 2008
|
Tag cloud control
posted at
11:37 PM
|
trackback
|
|
link
I recently decided to implement a tag cloud. I'm not quite sure why this grabbed me; I don't pay that much attention to them my own self. But the idea of how to do it interested me, so I gave it a bash as an ASP.NET custom Web server control[1]. I don't need a tag cloud control, and I bet that if you need one, you already have one. Basically, this was just a fun exercise for me.
Demo here: Tag Cloud Control Demo Source code here: TagCloud control source code
In a tag cloud, the various tags are displayed in a font size that's proportional to how many times the tag is used. A tag that's used a lot is big; a tag that's seldom used is small. Who knew, there are various ways to calculate this spread of font sizes. I ended up using an algorithm that I think (?) I found on a PHP site, I forget exactly.
This is what it looks like. This isn't live; to see a live one, go to the demo.

The control feeds off a list of items that contain a tag name and a tag count. How this list is generated would be, as they say, left as an exercise for the reader. I wrote the code so that it expects something that can be cast to IEnumerable. I played with it two ways. One was to create instances of a TagItem class (conveniently provided by myself) and stick them into a List<T> generic list (VB: List (Of T)) or an ArrayList object, both of which worked. I also was able to successfully give it a DataView object. Beyond that, no guarantees. :-) (Note that as of yet, I didn't implement this as a control that can do normal ASP.NET data binding. That'll be a v2.0, assuming I get that far.)
Given this list, the algorithm determines a total tag count and the highest and lowest tag count values. Imagine you have three tags: aspnet, used 100 times; books, used 40 times; and movies, used 20 times. Total tag count = 160; hi = 100; lo = 20. The tag range is 80.
The code then calculates a weight for each tag item. The weight represents where on the scale of lowest to highest tag count a specific tag item lies. The, um, formula is this:
weight = (itemTagCount - tagCountLo) / tagCountRange
For the example tags:
aspnet: (100 - 20) / 80 = 1.0 (Notice that the high is conveniently always 1)
books: (40 - 20) / 80 = .25
movies: (20 - 20) / 80 = 0.0 (Notice that the low is conveniently always 0)
The weight value is then mapped to the range of font sizes that you want to use. Suppose you decided that the tag cloud would display fonts between 8 and 24 points; the font size range is therefore 16. The formula for using the weight to get the font size would be:
fontSize = (weight * fontSizeRange) + minimumFontSize
For example:
aspnet: (1.0 * 16) + 8 = 24 (look, it's the highest possible font size)
books: (.25 * 16) + 8 = 12
movies: (0.0 * 16) + 8 = 8 (look, it's the lowest possible font size)
I would not be surprised to learn that there are better ways to calculate these relative font sizes. However, I don't think it matters that much ... the important issue is to have a roughly proportional difference in the font sizes. (This is also the point where a number of people point out to me that I could actually have done this in, like, 2 lines or something.)
Since I was doing this as a control, I exposed various properties. These include:- TagList (IEnumerable). A list that you provide that contains objects that in turn contain the tag names and tag counts. If you're stuck for objects to use, you can use the MikesControls.TagItem class to create individual tag items.
- MinimumFontSize, MaximumFontSize (int).
- IsHyperlink (Boolean). true (default) to create the tags as Hyperlink controls; false to create them as Label controls.
- HyperlinkFormat (String). A format string (e.g. "
?tag={0}") that's used for the NavigateUrl property if the tag is created as a Hyperlink control.
- HyperlinkData (enum). Specifies whether the tag display uses the tag name (default) or tag count. Probably not a useful property, much.
- TagNamePropertyName, TagCountPropertyName (String). The names of the properties in the tag item objects that are in the tag list. The control assumes it can find the tag name in a property named "tagName" and the tag count in a property named "tagCount". But maybe you have a list of objects with different property names.
- TagCssClass (String). Name of the CSS class that should be applied to each tag control, whether it's a Hyperlink or Label control. This avoids having the control emit a bunch of style junk.
- DisplayFormat (enum). Whether to create a cloud (separated by spaces) or list (separated by line breaks).
So that was fun for a little while. If I get motivated, I'll reimplement it with proper data binding, which of course is more complex, but more flexible. In the meantime, I might even add this to the blog, who knows.
[categories]
aspnet
|