Golden Tweets

Twitter published an article at the end of 2012 discussing some of the tweets that were retweeted the most times. These were marketed as golden tweets given the high levels of participation that they encouraged. When Barack Obama tweeted “Four more years”, it was retweeted nearly 1 million times. We will build a simple bar chart representing the number of times that the tweets mentioned in this article were retweeted. When hovering over the bars, the user name and number of times that their golden tweet was retweeted is shown.

You can View the demo here.

Getting started

We create a HTML document whose markup contains a brief overview of what this visualization is about and an anchor link that when pressed will draw our golden tweets chart. This anchor link will act to initialize an animation of the bars from zero width to a width representative of the number of associated retweets.

<h1>Golden Tweets</h1>
<p>The Twitter users responsible for the 5 
    most popular retweets...</p>
<p><a id="start">Draw Chart</a></p>
<div id="golden-tweets"></div>
<script type="text/javascript" 
    src="raphael-2.1.0-min.js"></script>
<script type="text/javascript" 
    src="jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="golden-tweets.js"></script>

We will write our JavaScript in the file golden-tweets.js.

Initializing bar drawing

The code for this chapter is initialized when the anchor tag with ID ‘start’ is clicked as shown below.
$('#start').click(function() {
    $(this).remove(); // Remove initializer link

    var paper = Raphael('golden-tweets', 770, 200);

    // ...
});

This element is removed when clicked and then our canvas is drawn.

Golden tweets data

The number of times that the golden tweets were retweeted is given below.

---------------------------------------------
User                Number of times retweeted
---------------------------------------------
@BarackObama        810,000
@justinbieber       220,000
@TJLang70           98,000
@yamachanoha        68,000
@TeamGB             67,000
---------------------------------------------

We define this data as an array of objects as follows, where the users name, Twitter username and number of retweets are expressed as the keys name, username and rt respectively.

var data = [
{
    name: 'Barack Obama',
    username: '@BarackObama',
    rt: 810000
},
{
    name: 'Justin Bieber',
    username: '@justinbieber',
    rt: 220000
},
// ...
];

The bar color custom attribute

We define a custom attribute that takes the number of retweets as a parameter named val and returns a fill based on this value as a proportion of the maximum number of retweets in our data set.

var maxValue = 810000;
paper.customAttributes.barColor = function(val) {
    var saturation = val / maxValue;
    return {
        fill: 'hsb(0.55,' + saturation + ',0.77)'
    };
};

We have fixed the values of hue and brightness at 0.55 and 0.77 respectively meaning that the resultant fill varies only in saturation. This value will be a varying shade of blue based on the ratio of the value to the highest number of retweets.

Drawing bars

To begin with, we define the height of the drawn bars and the maximum width of a bar (corresponding to the largest number of retweets). These values will be used to generate the bars as part of a loop through our data set. Labels identifying the username and number of retweets will stored in an array:

var barHeight = 40;
var barMaxWidth = 600;
var labels = Array();
for(var i = 0, ii = data.length; i < ii; i+=1) {
    (function(i) {
        // Drawing code …
    });
}

Notice that our drawing code is wrapped in a self-executing anonymous function with i passed as a variable. This ensures that any event handlers we define in side this function get the correct value of i.

We then create bars of zero width as follows:

var o = data[i]; // The i’th data object in our loop
var bar = paper.rect(0, i * barHeight, 0, barHeight);
bar.attr({
    'stroke-width': 0,
    barColor: o.rt
});

Our bar is a rectangle offset by its height multiplied by its index in our data array which will have the effect of creating a chart whose bars stem left to right. The barColor custom attribute is passed the number of retweets in the i'th data object and returns a fill as discussed in the previous section.

Animating Bars

In the same loop, having drawn the bars, we immediately initialize an animation on each of the bars, animating to a width that is a proportion of the maximum bar width defined as the number of retweets divided by the maximum number of retweets. When the animation is complete, we define a hover event handler on the bar which draws a text label giving the username and number of retweets in our data array.

var barWidth = barMaxWidth * (o.rt / maxValue);
bar.animate({width: barWidth}, 500, function() {
    // Animation is complete, draw labels on hover
    bar.hover(function() {
        var barText = paper.text(
            Bar.attr('width') + 12,
            ((i + 1) * barHeight) - (barHeight / 2),
            o.username + ' (' + o.rt + ')'
        );
        barText.attr('text-anchor', 'start');
        labels[i] = barText; // Store reference in labels array
    }, function() {
        labels[i].remove(); // remove the label from our canvas
    });
});

Note that our label is drawn at ((i + 1) * barHeight) - (barHeight / 2) which places it to the right of the drawn bar and centered about its height. Also note that when hovering out of the bar, we remove our label from our drawing canvas which ensures that a new label is never redrawn on top of an existing one.

Summary

This visualization demonstrates two techniques for comparing data values in data visualizations: (a) variations in colour by value and (b) variations in bar length based on value. Both these techniques are equally valid and you will see them utilized to great effect in daily newspapers and on blogs. That the chart allows users to interact with it in order to reveal values is one of the great advantages of creating visualizations using Raphaël.