Saturday 28 June 2008

Create a Flickr Tag Cloud in PHP


Sunset over Pewley Down, originally uploaded by Me (?).

Here is a very basic way of creating a Flickr tag cloud in PHP. To make the Flickr API calls simple I have used phpFlickr.

The what and the why are listed below but there is a worked example available also.

I am going to use these variables in the code:
$reqtags = 150; // Number of tags to display
$user = "xrrr"; // Flickr user to search for tags
$min_font = "10"; // Font size to start drawing tags
$max_font = "30"; // The maximum font size tags can get


First of all we need to convert the username string into a Flickr User ID. To do this use the flickr.people.findByUsername API function:
$ns = $f->people_findByUsername($user);
$nsid = $ns[nsid];


Then we obtain the tags from Flickr using the flickr.tags.getListUserPopular API function which returns an array of tags. The phpFlickr object will return an array of arrays. Each array contains the tag value and the count of the number of times the tag is used. We store the number of tags by counting the size of the array and sort the array by the tag count value:
$tags = $f->tags_getListUserPopular ($nsid, $reqtags);
$numtags = count ($tags);
sort ($tags);


We now calculate the number of tags that should be displayed at each font size. To do this we just divide the number of tags by the number of font sizes available (maximum font minus the minimum font) and round it down to the nearest whole number. Note if there are more font sizes than tags (in this example the user has less than 20 tags) then the interval will be zero. This is ok.
$increment = intval($numtags/($max_font-$min_font));


In order to calculate the font sizes we loop though the tag list (which is in tag count order) and create an associative array of "tag_name => font_size". This code is basic so does not attempt to calculate the font size from the tag count. It just loops through the array and every time the interval value is reached it increments the font size. If the interval value is zero then it just increments the font size for every tag.
$size = $min_font ;
for ($i=0; $i < $numtags; $i++) {
$output[$tags[$i][_content]] = $size ;
if ($increment == 0 || $i % $increment == 0 )
$size++;
}
}


We now have an associative array of tag and font size ordered by tag frequency. Tag clouds tend to be in alphabetical order so we sort by the associative array keys using the PHP function ksort:
ksort($output);


Finally we print out the HTML to build the tag cloud and link back to Flickr:
$url = "http://www.flickr.com/photos/$user/tags/" ;
echo "<div id='TagCloud'>";
foreach ($output as $tg => $sz) {
echo "&nbsp;<a href='".$url.$tg."' style='font-size: ".$sz."px;'>".$tg."</a> &nbsp; \n" ;
}
echo "</div>";


The resultant HTML can be styled with the following style sheet to make it look like Flickr:
<style>
body {
font-family:Arial,Helvetica,sans-serif;
}

#TagCloud {
background:#F5F5F5 none repeat scroll 0%;
border:1px solid #EEEEEE;
padding:15px;
}

#TagCloud a {
text-decoration:none;
}

#TagCloud a:link {
color:#0063DC;
}

#TagCloud a:visited {
color:#0063DC;
}

#TagCloud a:hover {
background:#0063DC none repeat scroll 0% 0%;
color:#FFFFFF;
text-decoration:none;
}
</style>


I have created a working example to demonstrate the code and make it easier to reuse.

Tuesday 3 June 2008

Groopy Search by Group Update


Groopy v3, originally uploaded by Me (?).


Today I have created a new 'advanced' search page that allows you to search for your photos in a particular group.

Click the 'advanced search' link on the front page or bookmark this link.

Monday 2 June 2008

Groopy Performance Update


Streaky Bus, originally uploaded by Me (?).

I released version 0.2 of Flickr Groopy today. Aside from some code tidy ups the main updates are:
  • I found out that you can obtain the number of views of a photo from the search meaning that I can bypass one of the slow API calls. It now takes half the time to render a screen of images. Simply add 'extras=>views' into the request for flickr.photos.search and it means that the flickr.photos.getInfo call can be missed out entirely
  • I have changed the sort order to sort by 'relevance' rather than 'interestingness-desc' - I will be making the sort order a user option at some point
Link to Groopy: xrrr.co.uk/groopy