Twitterspace

Context

  • Indiana University (Bloomington, IN)
  • Ph.D. project (co-creator)

Case

Requirements: I was tasked with creating the front end in Haxe and Actionscript for a prototype to take a tweets of the those a Twitter account was following and display them animating across the screen.

This is the draw function in the Tweet class, responsible for creating the individual tweets.
public function draw() {
        if (user_screen_name == "wnryan") {
			boxColor = 0x430000;
        }

	//a movie clip to store the background of the tweet
	var base:MovieClip = new MovieClip();

	//draw the elipse to form the background and call it background box
	base.graphics.beginFill(boxColor);
	base.graphics.lineStyle(1, borderColor);
	base.graphics.drawRoundRect(boxX, boxY, boxWidth, boxHeight, 25, 25); //fix this ellipse
	base.graphics.endFill();
	base.name = "background box";
	addChild(base);  //add it to this tweet (which is a movie clip itself)

	//add a text format
	var format:TextFormat = new TextFormat();
	format.font = "Arial";
	format.color = textColor;
	format.size = textSize;

	//setup the text properly and give it a name tweet
	tweetText = new TextField();
	tweetText.selectable = false;
	tweetText.embedFonts = true;
	tweetText.wordWrap = true;
	tweetText.antiAliasType = "advanced";
	tweetText.type = "dynamic";
	tweetText.name = "tweet";

	tweetText.defaultTextFormat = format;
	tweetText.htmlText = message; //assign what the tweet is

	//position the text and give it a box
	tweetText.x = boxX + textX;
	tweetText.width = textWidth;
	tweetText.height = textHeight;

	addChild(tweetText);   //add it to this tweet (which is a movie clip itself)

	//load the image for this user externally and name this user image
	var ldImage : Loader = new Loader();
	var url:String = profile_image_url;

	try {
		var urlReq:URLRequest = new URLRequest(url);
		ldImage.load(urlReq);
	} catch (error:String) {
	    	trace("Unable to load URL: "+url);
                trace("Error: "+error);
        }
	ldImage.name = "user image";

	//position and size this image
	ldImage.x = boxX + imageX;
	ldImage.y = boxY + imageY;
	ldImage.scaleX = 0.6;//imageHeight / ldImage.content.width;
	ldImage.scaleY = 0.6;//imageWidth / ldImage.content.height;

	addChild(ldImage); //add it to this tweet (which is a movie clip itself)
}
This is the onEnterFrame for the Main class, which is responsible for animating the Tweets and also updating any tweets already on the screen.
public function onEventFrame(evt:Event) :Void {

   for (i in 0...tweets.length) {
       //go through all the tweets
       if (tweets[i].direction) {
            //if the direction is true, move them to the right
            if (tweets[i].x > scrWidth) {
                //if they are at the end of the screen, place them before the front of the screen
                tweets[i].x = ( - 1 * tweets[i].boxWidth);
            } else {
                tweets[i].x += Math.ceil(tweets[i].movementRate);
            }
        } else {
            //if the direction is false, move them to the left
            if (tweets[i].x < ( - 1 * tweets[i].boxWidth)) {
                //if they are at the front of the screen, place them after the end of the screen
                tweets[i].x = scrWidth;
            } else {
                tweets[i].x -= Math.ceil(tweets[i].movementRate);
            }
        }
     }
     if (loadingNewTweet) {
        // if we had a new tweet popup
        if (newBox.alpha < 0.8) {
            // fade in our tweet to 80% alpha
            newBox.alpha = newBox.alpha + 0.05;
        } else {
            loadingNewTweet = false;
        }
     }
     if (unloadingNewTweet) {
         // if we are getting ride of the popup
         if (newTweet.hitTestPoint(newTweetCurX + 1, newTweetCurY + 1) || newBox.alpha <= 0) {
            //if we hit the pop up on the tweet that it is or it is no longer visible
            unloadingNewTweet = false;
            removeNewBox();
            // remove the pop up
         } else {
      	    newBox.alpha = newBox.alpha - 0.04;
            //gradually fade out the box
            //this was arrived at through trial and error and looks reasonably good, there is a difference in the jumps along x and y
            //because this will generally need to travel farther on the x coordinate than y
            newBox.x += ((newTweet.x + newTweet.width / 2) - newTweetCurX) / 10 + (0.1 * newBox.width);
            // jump 1/10 the distance to the tweet and also take into account what was lost through scaling
            newTweetCurX += ((newTweet.x + newTweet.width / 2) - newTweetCurX) / 10;
            //move the representation for the center point by this amount (with out the scaling
            newBox.y += ((newTweet.y + newTweet.height / 2) - newTweetCurY) / 5 + (0.1 * newBox.height);
            // jump 1/5 the distance to the tweet and also take into account what was lost through scaling
            newTweetCurY += ((newTweet.y + newTweet.height / 2) - newTweetCurY) / 5;
            //move the representation for the center point by this amount (with out the scaling
            //gradually shrink the box
            newBox.scaleX = newBox.scaleX * 0.9;
            newBox.scaleY = newBox.scaleY * 0.9;
      	}
   }
}

Result: Using the Twitter API, we created an external database of community Tweets. The front end took that data, pulled user information, and animated it using the Haxe interface via Actionscript.

twitterspace_popup

This is an example image of the working system. The real system is no longer pulling data from Twitter due to changes in the API.

Click here to see an example with sample data.

Outcomes: The Twitterspace display was deployed for our school as well as 3 academic conferences and 3 other organizations.

Details

Dates of Project: Jan 2007-Dec 2010

Development Skills Used: Haxe, Actionscript, Audacity

My Roles: Research, Design, Writing, Programming, Artistry