March Madness 8 – Tumblin’ Tumblr Tumbleweeds
Uncategorized
Add comments
Mar 092010
For today’s March Madness program I made a visualization of Tumblr quotes from a few friends I follow. I turn the text into a tumbleweed and let it ramble on by across the screen. It could definitely use some optimization as canvas doesn’t seem to handle lots of text rendering too well. Source is after the break.
JPLT.Class.create("JPLT.TextTumbleweed", JPLT.Object, function(str) { this.str = str; this.reset(); this.createPhrases(); }, { reset: function() { this.active = false; this.x = -50 + Math.random() * -200; this.y = 267 + 133 * Math.random(); this.baseY = this.y; this.speed = Math.random() * 5 + 1; this.r = Math.random() * Math.PI/8 - Math.PI/16; this.size = 10 + Math.random()*10; this.color = "rgb(" + Math.floor(Math.random()*50) + "," + Math.floor(Math.random()*50) + "," + Math.floor(Math.random()*50) + ")"; }, run: function() { if (this.active) { this.r += this.speed/5 * Math.PI/16; if (this.r > Math.PI*2) { this.r -= Math.PI*2; } this.x += this.speed; this.y = this.baseY + Math.abs(Math.cos(this.r)) * this.speed * 5; if (this.x > window.innerWidth + 200) { this.reset(); this.fireEvent("weedInactive"); } } }, createPhrases: function() { var phrase; var words = this.str.split(/\s+/); this.phrases = []; while(words.length) { phrase = ""; while(words.length && phrase.length < 25) { phrase = phrase + words.shift() + " "; } this.phrases.push({ 'phrase': phrase, 'random': Math.random() }); } }, paint: function(ctx) { try { if (this.active) { var random; var phrase; var r = this.r; ctx.save(); ctx.fillStyle = this.color; ctx.translate(this.x,this.y); for (var i=0; i<this.phrases.length; i++) { phrase = this.phrases[i].phrase; random = this.phrases[i].random; ctx.rotate(r); ctx.font = this.size + "px sans-serif"; var size = ctx.measureText(phrase); ctx.fillText(phrase,-size.width/2,0); r = Math.PI + Math.PI/(5 + -random*3); } ctx.restore(); } } catch (e) { throw(e); } } } ); JPLT.Class.create("JPLT.TumblrTumbleweeds", JPLT.Object, function() { // We need a global reference to call back. JPLT.TumblrTumbleweeds.instance = this; this.width = 800; this.height = 534; this.delay = 10; this.quoteLength = 200; this.activeWeeds = 2; this.weeds = []; this.addEventListener("weedInactive", this.delegate(this.activateWeed)); this.createElements(); this.load('soupsoup'); this.load('justinday'); this.load('ericmortensen'); this.load('jacobjoaquin'); this.load('mikehudack'); }, { getUrl:function(user) { var url = "http://" + escape(user) + ".tumblr.com/api/read/json?type=quote&" + "callback=JPLT.TumblrTumbleweeds.instance.loaded"; return url; }, load:function(user) { var script = document.createElement('script'); script.type = "text/javascript"; script.src = this.getUrl(user); var body = document.documentElement || document.body; body.appendChild(script); }, stripHtml: function(str) { return str.replace(/<.+?>/,"").replace(/&#\d+;/,""); }, excerptize: function(str) { if (str.length > this.quoteLength) { str = str.substr(0,this.quoteLength-3) + "..."; } return str; }, createTumbleweed: function(str) { var weed = new JPLT.TextTumbleweed(str); this.weeds.push(weed); }, activateWeed: function() { var weed; for (var i=0; i<10; i++) { weed = this.weeds[Math.floor(Math.random() * this.weeds.length)]; if (!weed.active) { this.log("Activating " + weed.str); weed.active = true; return; } } window.setTimeout(this.delegate(this.activateWeed), 5000); }, loaded:function(data) { var posts = data.posts; for (var i=0; i<posts.length; i++) { this.createTumbleweed(this.excerptize(this.stripHtml(posts[i]['quote-text']))); } this.run(); }, createElements: function() { this.background = document.createElement("img"); this.background.src = "image.jpg"; this.background.style.position = "absolute"; this.background.style.top = window.innerHeight/2 - this.height/2 + "px"; this.background.style.left = window.innerWidth/2 - this.width/2 + "px"; this.element = document.createElement("canvas"); this.element.width = this.width; this.element.height = this.height; this.element.style.position = "absolute"; this.element.style.top = window.innerHeight/2 - this.height/2 + "px"; this.element.style.left = window.innerWidth/2 - this.width/2 + "px"; this.element.style.zIndex = 1; var body = document.documentElement || document.body; body.appendChild(this.background); body.appendChild(this.element); }, context: function() { return this.element.getContext("2d"); }, run: function() { if (!this.timer) { for (var i=0; i<this.activeWeeds; i++) { this.activateWeed(); } this.timer = window.setInterval(this.delegate(this.paint), this.delay); } }, stop: function() { window.clearInterval(this.timer); for (var i=0; i<this.weeds.length; i++) { this.weeds[i].reset(); } this.timer = null; }, clear: function() { var ctx = this.context(); ctx.clearRect(0,0,this.width,this.height); }, paint: function() { var weed; var ctx = this.context(); try { this.clear(); for (var i=0; i<this.weeds.length; i++) { weed = this.weeds[i]; weed.run(); weed.paint(ctx); } } catch (e) { stop(); throw(e); } } } ); |

