Changed drawing from SVG to Canvas
authorveltr
Wed, 17 Apr 2013 17:10:43 +0200
changeset 20 8b0a464fb5ac
parent 19 685c406c7d8c
child 21 007254e97333
Changed drawing from SVG to Canvas
css/playscreen.css
js/playscreen.js
playscreen-frame.html
playscreen.html
--- a/css/playscreen.css	Tue Apr 16 18:26:43 2013 +0200
+++ b/css/playscreen.css	Wed Apr 17 17:10:43 2013 +0200
@@ -96,7 +96,7 @@
 	background-position: -36px -18px;
 }
 
-.play-svg {
+.play-canvas {
     position: absolute; left: 0; top: 0; width: 100%; height: 100%;
 }
 
@@ -187,9 +187,14 @@
 }
 
 .play-tagcloud li {
-	float: left; width: 98px; height: 10px;
-	line-height: 10px;
-    text-align: center; cursor: pointer;
+    cursor: pointer;
+    float: left;
+    height: 16px;
+    line-height: 16px;
+    text-align: center;
+    width: 98px;
+    display: inline-block;
+    margin-bottom: -6px;
 }
 
 .play-tagcloud li.selected {
@@ -204,19 +209,6 @@
 	margin-top: 10px;
 }
 
-.local-position, .global-position {
-	position: absolute; height: 1px;
-	background: #FF00FC;
-}
-
-.global-position {
-	left: 0; width: 125px;
-}
-
-.local-position {
-	left: 155px; width: 215px;
-}
-
 .user-tweets {
 	position: absolute; left: 730px; top: 300px; bottom: 0; right: 0; display: none;
 }
--- a/js/playscreen.js	Tue Apr 16 18:26:43 2013 +0200
+++ b/js/playscreen.js	Wed Apr 17 17:10:43 2013 +0200
@@ -223,20 +223,77 @@
         tb.html(tbhtml);
         tb.css("top",0);
         
-        showTopicViz();
+        throttledShowLocal();
     }
+           
+    
+    
+    var images = {},
+    	playTime = $(".current-time");
+    
+	var globW = 85,
+        globL = 40,
+        entonnoirR = 155,
+        localL = 235,
+        localW = 85,
+        localR = (localL + localW),
+        localTimeR = (localL + localW) + globL,
+        globR = (globW + globL),
+        mx = Math.max.apply(Math, data.minutes.map(function(s) { return s.count})),
+        xscale = globW/mx,
+        yscale,
+        localyscale,
+        filteredSegments = [];
     
-    var tweetLines = [];
-    
-    function showTopicViz() {
+    function showLocal() {
+    	var $c = $(".play-canvas"),
+    		c = $c[0],
+    		ph = $c.height(),
+    		pw = $c.width();
+        
+        yscale = ph / data.duration;
+		localyscale = ph / localduration;
+		
+		var localstart = localpos - localduration/2;
+    		localend = localpos + localduration/2;
+    		globtop = yscale * localstart,
+    		globbottom = yscale * localend,
+    		betweenx = (globR + entonnoirR) / 2,
+    		betweenyt = (globtop) / 2,
+    		betweenyb = (globbottom + ph) / 2,
+    		curve = (entonnoirR - globR) / 2,
+        
+    	c.width = pw;
+    	c.height = ph;
+    	
+    	var ctx = c.getContext('2d');
+    	
+    	ctx.clearRect(0,0, pw, ph);
+    	
+    	/* Tracé de l'entonnoir */
+    	
+    	ctx.beginPath();
+    	
+    	ctx.moveTo(0, globtop);
+    	ctx.lineTo(globR, globtop);
+    	ctx.quadraticCurveTo(betweenx, globtop, betweenx, Math.max(globtop - curve, betweenyt));
+    	ctx.lineTo(betweenx, Math.min(curve, betweenyt));
+    	ctx.quadraticCurveTo(betweenx, 0, entonnoirR, 0 );
+    	ctx.lineTo(localR,0);
+    	ctx.lineTo(localR, ph);
+    	ctx.lineTo(entonnoirR, ph);
+    	ctx.quadraticCurveTo(betweenx, ph, betweenx, Math.max(ph - curve, betweenyb));
+    	ctx.lineTo(betweenx, Math.min(globbottom + curve, betweenyb));
+    	ctx.quadraticCurveTo(betweenx, globbottom, globR, globbottom, globbottom);
+    	ctx.lineTo(0,globbottom);
+    	ctx.fillStyle = '#222222';
+    	ctx.fill();
+
+		
         var selectedBlocks = $(".topic.selected, .topic.hover"),
             sbl = selectedBlocks.length,
-            topicBlocks = $(".topic");
-        if (!sbl && topicBlocks.length < sortedTopics.length) {
-            selectedBlocks = topicBlocks;
-            sbl = selectedBlocks.length;
-        }
-        var topicsAndColors = [],
+            topicBlocks = $(".topic"),
+            topicsAndColors = [],
         	colors = {};
         selectedBlocks.each(function() {
             var el = $(this),
@@ -258,259 +315,223 @@
             colors[topic.id] = topic.color;
             topic.$.css("background", topic.color);
         });
-        
+
+		/* Tracé des MMSOs */
+		
+		var localkeywords = {};
+		
+		filteredSegments = [];
+		
         for (var i = 0; i < nmmso; i++) {
-            var opacity = 0,
+            var mmso = data.segments[i],
+            	opacity = 0,
                 rgb = [0,0,0];
             topicsAndColors.forEach(function(topic) {
-                var c = Raphael.getRGB(topic.color),
-                    o = topic.topic.weights[i];
-                rgb[0] += c.r * o;
-                rgb[1] += c.g * o;
-                rgb[2] += c.b * o;
+            	var o = topic.topic.weights[i];
+                rgb[0] += parseInt(topic.color.substr(1,2),16) * o;
+                rgb[1] += parseInt(topic.color.substr(3,2),16) * o;
+                rgb[2] += parseInt(topic.color.substr(5,2),16) * o;
                 opacity += o;
             });
+            var isinlocal = (mmso.end > localstart && mmso.start < localend);
+            if (isinlocal) {
+            	filteredSegments.push(mmso);
+				var y = localyscale * (mmso.start - localstart),
+					h = localyscale * mmso.duration,
+					visibled = (
+						mmso.start < localstart
+						? mmso.duration - localstart + mmso.start
+						: (
+							mmso.end > localend
+							? mmso.duration - mmso.end + localend
+							: mmso.duration
+						)
+					);
+				_(mmso.keywords).each(function(v,k) {
+					localkeywords[k] = (v * visibled) + (localkeywords[k] || 0);
+				});
+            }
             if (opacity) {
-                color = Raphael.rgb.apply(Raphael, rgb.map(function(c) {
-                    return c/opacity;
-                }));
-                var attr = {
-                    fill: color,
-                    opacity: .5 + .5 * opacity
-                };
-                segmentrects[i].show();
-                segmentrects[i].attr(attr);
-                if (i >= localMmsoDelta && i < localMmsoDelta + localMmsos.length) {
-                	localMmsos[i - localMmsoDelta].show();
-                	localMmsos[i - localMmsoDelta].attr(attr);
-                }
-            } else {
-                segmentrects[i].hide();
-                if (i >= localMmsoDelta && i < localMmsoDelta + localMmsos.length) {
-                	localMmsos[i - localMmsoDelta].hide();
+                rgb = rgb.map(function(c) {
+                    return parseInt(c/opacity);
+                });
+                ctx.fillStyle = 'rgba(' + rgb.join(',') + ',' + opacity + ')';
+                ctx.fillRect(globL, yscale * mmso.start, globW, yscale * mmso.duration);
+                if (isinlocal) {
+					ctx.fillRect( localL, y, localW, h );
                 }
             }
         }
         
-        tweetLines.forEach(function(tl) { tl.remove(); });
-        tweetLines = [];
+        /* Tracé des courbes de nombres de tweets */
+        
+        var styles = [
+	        {
+	        	lineWidth: 4,
+	        	strokeStyle: "rgba(0,0,0,.5)"
+	        },
+	        {
+	        	lineWidth: 1,
+	        	strokeStyle: "#ffffff"
+	        }
+        ]
+        
+        styles.forEach(function(s) {
+        	ctx.beginPath();
+        	data.minutes.forEach(function(m, i) {
+        		var x = globL + xscale * m.count,
+        			y1 = yscale * (m.from + 20),
+        			y2 = yscale * (m.from + 40);
+        		if (i) {
+        			ctx.lineTo(x,y1);
+        		} else {
+        			ctx.moveTo(x,y1);
+        		}
+        		ctx.lineTo(x,y2);
+        	});
+        	_(s).each(function(v, k) {
+        		ctx[k] = v;
+        	});
+        	ctx.stroke();
+        });
+        
+		var filteredFiveSecs = data.fiveseconds.slice(Math.floor(localstart / 5), Math.ceil(localend / 5));
+        var counts = filteredFiveSecs.map(function(s) { return s.count}),
+        	lmx = Math.max.apply(Math, counts),
+        	lmi = Math.min.apply(Math, counts.concat([lmx - 1]))
+        	lxscale = localW/(lmx-lmi);
+        	
+       	styles.forEach(function(s) {
+        	ctx.beginPath();
+        	filteredFiveSecs.forEach(function(m, i) {
+        		var x = localL + lxscale * (m.count - lmi),
+        			y1 = localyscale * (m.from + 1 - localstart),
+        			y2 = localyscale * (m.from + 4 - localstart);
+        		if (i) {
+        			ctx.lineTo(x,y1);
+        		} else {
+        			ctx.moveTo(x,y1);
+        		}
+        		ctx.lineTo(x,y2);
+        	});
+        	_(s).each(function(v, k) {
+        		ctx[k] = v;
+        	});
+        	ctx.stroke();
+        });
         
         var deltaY = $(".play-bottom").offset().top;
         
         $(".play-localtweets .tweet:visible").each(function() {
         	var el = $(this),
         		liY = + el.offset().top + el.outerHeight() / 2 - deltaY,
-        		tY = localyscale * (+el.attr("data-timestamp") - localpos + localduration / 2),
-        		p = "M" + localL + "," + tY + "L" + localR + "," + tY + "L400," + liY,
-        		path = paper.path(p);
+        		tY = localyscale * (+el.attr("data-timestamp") - localpos + localduration / 2);
+    		ctx.beginPath();
+    		ctx.strokeStyle = "#ccc";
+    		ctx.moveTo(localL, tY);
+    		ctx.lineTo(localR, tY);
+    		ctx.lineTo(400, liY);
+    		ctx.stroke();
     		$(this).css("background",colors[el.attr("data-topic-id")] || "");
-    		path.attr({
-    			stroke: "#ccc"
-    		});
-    		tweetLines.push(path);
         });
         
-    }
-    
-    var jqsvg = $(".play-svg"),
-        paper = new Raphael(jqsvg[0]),
-        totalR = jqsvg.width(),
-        ph = jqsvg.height(),
-        globW = 85,
-        globL = 40,
-        entonnoirR = 155,
-        localL = 235,
-        localW = 85,
-        localR = (localL + localW),
-        localTimeR = (localL + localW) + globL,
-        globR = (globW + globL),
-        yscale = ph / data.duration,
-        mx = Math.max.apply(Math, data.minutes.map(function(s) { return s.count})),
-        xscale = globW/mx;
-    var segmentrects = data.segments.map(function(mmso) {
-        var rect = paper.rect(globL, yscale * mmso.start, globW, yscale * mmso.duration);
-        rect.attr({stroke: "none"});
-        return rect;
-    });
-    
-    var d = "M" + data.minutes.map(function(s) {
-            var x = globL + xscale * s.count;
-            return x
-                + ","
-                + yscale * (s.from + 20)
-                + "L"
-                + x
-                + ","
-                + yscale * (s.from + 40);
-        }).join("L");
+        ctx.fillStyle = '#ffffff';
+        ctx.strokeStyle = '#999999';
+        ctx.font = '10px Arial,Helvetica';
+        
+        function line(x1,y1,x2,y2) {
+        	ctx.beginPath();
+			ctx.moveTo(x1, y1);
+			ctx.lineTo(x2, y2);
+			ctx.stroke();
+        }
         
-    paper.path(d).attr({
-        "stroke-width": 4,
-        "stroke": "#000000",
-        opacity: .5
-    });
-    paper.path(d).attr({
-        "stroke-width": 1,
-        "stroke": "#ffffff"
-    });
-    
-    for (var i=0; i < data.duration; i += 1800) {
-        var y = yscale * i;
-        paper.path("M0" + "," + y + "l" + globR + ",0").attr({stroke: "#666"});
-        paper.text(0, y + 6, secsToString(i)).attr({
-        	"text-anchor": "start",
-            "fill": "#ffffff"
-        });
-    }
-    paper.text(0, ph-8, secsToString(data.duration)).attr({
-        "text-anchor": "start",
-        "fill": "#ffffff"
-    });
-    paper.path("M0" + globR + ",0L" + localTimeR + ",0" ).attr({stroke: "#666"});
-    paper.path("M0," + (ph-1) + "l" + localTimeR + ",0" ).attr({stroke: "#666"});
-    
-    paper.path("M" + globR + ",0l0," + ph).attr({stroke: "#666"});
-    paper.path("M" + localL + ",0l0," + ph).attr({stroke: "#666"});
-    
-    var entonnoir = paper.path("").attr("fill","#333"),
-    	localStartText = paper.text(localTimeR,6,"").attr({
-    		"text-anchor": "end",
-    		"fill": "#ffffff"
-    	}),
-    	localEndText = paper.text(localTimeR,ph - 8, "").attr({
-    		"text-anchor": "end",
-    		"fill": "#ffffff"
-    	}),
-    	localTimes = [],
-    	localMmsos = [],
-    	localMmsoDelta,
-    	mmsoAlt = [],
-    	lowerFiveSecs,
-    	higherFiveSecs,
-    	localyscale;
-	
-	entonnoir.toBack();
-    
-    var cloudTemplate = _.template('<li style="font-size: <%- size %>px;"<% if (selected) {%> class="selected"<% } %>><%- word %></li>');
-    
-    var globalIndic = $(".global-position"),
-    	localIndic = $(".local-position"),
-    	playTime = $(".current-time");
-    
-    function showLocal() {
-		localyscale = ph / localduration;
-    	var localstart = localpos - localduration/2;
-    		localend = localpos + localduration/2;
-    		globtop = yscale * localstart,
-    		globbottom = yscale * localend,
-    		betweenx = (globR + entonnoirR) / 2,
-    		betweenyt = (globtop) / 2,
-    		betweenyb = (globbottom + ph) / 2,
-    		curve = (entonnoirR - globR) / 2,
-    		entonnoird = "M0," + globtop + "l" + globR + ",0Q" + betweenx + "," + globtop + "," + betweenx + ","
-    			+ Math.max(globtop - curve, betweenyt) + "L" + betweenx + "," + Math.min(curve, betweenyt) + "Q"
-    			+ betweenx + ",0," + entonnoirR + ",0"
-    			+ "L" + localR + ",0L" + localR + "," + ph + "L" + entonnoirR + "," + ph + "Q" + betweenx + "," + ph + ","
-    			+ betweenx + "," + Math.max(ph - curve, betweenyb) +"L" + betweenx + "," + Math.min(globbottom + curve, betweenyb)
-    			+ "Q" + betweenx + "," + globbottom + "," + globR + "," + globbottom + "L0," + globbottom,
-			localkeywords = {};
-			
-		entonnoir.attr("path",entonnoird);
-    	localIndic.css("top",(player.currentTime - localstart) * localyscale);
-		localTimes.forEach(function(t) {
-			t.text.remove();
-			t.line.remove();
-		});
-		localMmsos.forEach(function(t) {
-			t.remove();
-		});
-		mmsoAlt.forEach(function(t) {
-			t.remove();
-		});
-		var filteredSegments = data.segments.filter(function(s) {
-			return s.start < localend && s.end > localstart;
-		});
-		localMmsoDelta = parseInt(filteredSegments[0].id.split("_")[1]);
-		localMmsos = filteredSegments.map(function(s) {
-			var y = localyscale * (s.start - localstart),
-				h = localyscale * s.duration,
-				rect = paper.rect( localL, y, localW, h ),
-				visibled = (
-					s.start < localstart
-					? s.duration - localstart + s.start
-					: (
-						s.end > localend
-						? s.duration - s.end + localend
-						: s.duration
-					)
-				);
-			_(s.keywords).each(function(v,k) {
-				localkeywords[k] = (v * visibled) + (localkeywords[k] || 0);
-			});
-	        rect.attr({stroke: "none", title: s.id});
-	        if (parseInt(s.id.replace("MMSO_","")) % 2) {
-	        	var altrect = paper.rect( localR, y, 60, h);
-	        	altrect.attr({stroke: "none", fill: "#222"});
-	        	mmsoAlt.push(altrect);
-	        }
-	        return rect;
-		});
-		localStartText.attr("text", secsToString(localstart)).toFront();
-		localEndText.attr("text", secsToString(localend)).toFront();
+		line(0, 0, localTimeR, 0);
+		line(0, ph-1, localTimeR, ph-1 );
+		line(globR, 0, globR, ph);
+		line(localL, 0, localL, ph);
+		
+		/* Global Times */
+		ctx.fillText(secsToString(data.duration), 0, ph - 3);
+		 
+	    for (var i=0; i < data.duration; i += 1800) {
+	        var y = yscale * i;
+	        line(0, y, globR, y);
+	        ctx.fillText(secsToString(i), 0, y+9);
+	    }
+		
+        /* Local Times */
+        ctx.fillText(secsToString(localstart), localTimeR - 30, 9);
+        ctx.fillText(secsToString(localend), localTimeR - 30, ph - 3);
+	    
 		for ( var i = (1 + Math.floor(localstart / 120)) * 120; i < localend; i += 120 ) {
-			var y = localyscale*(i - localstart)
-			localTimes.push({
-				text: paper.text(localTimeR,6+y,secsToString(i)).attr({
-		    		"text-anchor": "end",
-		    		"fill": "#ffffff"
-		    	}),
-		    	line: paper.path("M0" + localL + "," + y + "L" + localTimeR + "," + y).attr({stroke: "#666"})
-			});
-		}
-		if (lowerFiveSecs) {
-			lowerFiveSecs.remove();
-		}
-		if (higherFiveSecs) {
-			higherFiveSecs.remove();
+			var y = localyscale*(i - localstart);
+			ctx.fillText(secsToString(i), localTimeR - 30, 9+y);
+			line(localL, y, localTimeR, y);
 		}
-		var filteredFiveSecs = data.fiveseconds.slice(Math.floor(localstart / 5), Math.ceil(localend / 5));
-        var counts = filteredFiveSecs.map(function(s) { return s.count}),
-        	lmx = Math.max.apply(Math, counts),
-        	lmi = Math.min.apply(Math, counts.concat([lmx - 1]))
-        	lxscale = localW/(lmx-lmi);
-       	
-	    var d = "M" + filteredFiveSecs.map(function(s) {
-	            var x = localL + lxscale * (s.count - lmi);
-	            return x
-	                + ","
-	                + localyscale * (s.from + 1 - localstart)
-	                + "L"
-	                + x
-	                + ","
-	                + localyscale * (s.from + 4 - localstart);
-	        }).join("L");
-	        
-	    lowerFiveSecs = paper.path(d).attr({
-	        "stroke-width": 4,
-	        "stroke": "#000000",
-	        opacity: .5
-	    });
-	    higherFiveSecs = paper.path(d).attr({
-	        "stroke-width": 1,
-	        "stroke": "#ffffff"
-	    });
-	    
-	    var imghtm = '', imgrate = localduration / 12, imgstart = imgrate * Math.floor(localstart / imgrate), imgend = imgrate * Math.ceil(localend / imgrate);
-	    for (var i = imgstart; i <= imgend; i+= imgrate) {
+		
+		
+		var imgw = 80,
+			imgh = 45,
+			imgrate = localduration / 12,
+			imgstart = imgrate * Math.floor(localstart / imgrate),
+			imgend = imgrate * Math.ceil(localend / imgrate);
+		
+		for (var i = imgstart; i <= imgend; i+= imgrate) {
 	    	var imgsrc = i + '.png';
 	    	while (imgsrc.length < 9) {
 	    		imgsrc = '0' + imgsrc;
 	    	}
-	    	var imgy = Math.floor( localyscale * (i - localstart) - 22.5 )
-	    	imghtm += '<img src="thumbnails/' + imgsrc + '" style="top: ' + imgy +'px;" />';
+	    	if (images[i]) {
+	    		if (images[i].width) {
+	    			ctx.drawImage(images[i], entonnoirR, localyscale * (i - localstart) - imgh / 2, imgw, imgh);
+	    		}
+	    	} else {
+	    		var img = new Image();
+	    		img.onload = function() {
+	    			throttledShowLocal();
+	    		}
+	    		img.src = 'thumbnails/' + imgsrc;
+	    		images[i] = img;
+	    	}
 	    }
-	    $(".play-images").html(imghtm);
 	    
+		if (player) {
+			var yg = yscale * player.currentTime,
+				yl = (player.currentTime - localstart) * localyscale,
+				betweeny = (yg + yl) / 2,
+				styles = [
+			        {
+			        	lineWidth: 4,
+			        	strokeStyle: "rgba(0,0,0,.5)"
+			        },
+			        {
+			        	lineWidth: 1,
+			        	strokeStyle: "#ff00cc"
+			        }
+		        ];
+	        
+	        styles.forEach(function(s) {
+	        	ctx.beginPath();
+				ctx.moveTo(0, yg);
+				if (player.currentTime >= localstart && player.currentTime <= localend) {
+					ctx.lineTo(globR, yg);
+			    	ctx.quadraticCurveTo(betweenx + 3, yg, betweenx + 3, yg > yl ? Math.max(yg - curve, betweeny) : Math.min(yg + curve, betweeny));
+			    	ctx.lineTo(betweenx + 3, yg < yl ? Math.max(yl - curve, betweeny) : Math.min(yl + curve, betweeny));
+			    	ctx.quadraticCurveTo(betweenx + 3, yl, entonnoirR + 6, yl );
+			    	ctx.lineTo(localR, yl);
+			    } else {
+			    	ctx.lineTo(betweenx, yg);
+			    }
+	        	
+	        	_(s).each(function(v, k) {
+	        		ctx[k] = v;
+	        	});
+	        	ctx.stroke();
+	        });
+			
+		}
+		
 	    $(".play-localtweets .tweet").each(function() {
 	    	var el = $(this),
 	    		t = parseInt(el.attr("data-timestamp"));
@@ -529,36 +550,56 @@
 	    	.sortBy(function(w) {
 	    		return -w.score;
 	    	})
-	    	.first(40)
+	    	.first(39)
 	    	.value();
     	
     	var values = _(localkeywords).pluck('score'),
     		max = Math.max.apply(Math, values),
     		min = Math.min.apply(Math, values),
     		scale = 10 / (max - Math.min(max - .1, min)),
-    		selectedVisible = false;
-		
-		localkeywords.forEach(function(w) {
-			w.size = 10 + (w.score - min) * scale;
-			w.selected = (w.word === selectedWord);
-			selectedVisible = selectedVisible || w.selected;
+    		selectedVisible = false,
+    		tc = $(".play-tagcloud li");
+    		
+		localkeywords.forEach(function(w, i) {
+			var size = 10 + (w.score - min) * scale,
+				selected = (w.word === selectedWord),
+				e = $(tc[i]),
+				t = e.text();
+			if (t !== w.word) {
+				e.text(w.word);
+			}
+			e.css("font-size", size + "px");
+			if (selected) {
+				e.addClass("selected");
+			} else {
+				e.removeClass("selected");
+			}
+			selectedVisible = selectedVisible || selected;
 		});
+		if (localkeywords.length < 39) {
+			for (var i = localkeywords.length; i < 39; i++) {
+				$(tc[i]).text("").removeClass("selected");
+			}
+		}
     	
     	if (!selectedVisible) {
     		selectedWord = false;
     	}
-    	
-    	$(".play-tagcloud").html(localkeywords.map(cloudTemplate).join(""));
-	    
+    	    
 		throttledGetTweets();
-		showTopicViz();
+    }
+    
+    for (var i = 0; i < 39; i++) {
+    	$(".play-tagcloud").append("<li>");
     }
     
-    $(".play-tagcloud").on("click","li", function() {
-    	if ($(this).hasClass("selected")) {
+    $(".play-tagcloud li").click(function() {
+    	
+    	var w = $(this).text();
+    	if (w === selectedWord) {
     		selectedWord = false;
     	} else {
-    		selectedWord = $(this).text();
+    		selectedWord = w;
     	}
     	throttledShowLocal();
     });
@@ -584,8 +625,7 @@
     	var toshow = [];
     	var topics = Array.prototype.join.call($(".topic.selected").map(function(){return $(this).attr("data-topic-id")})).split(",");
     	
-    	for (var i = 0; i < localMmsos.length; i++) {
-    		var mmso = data.segments[localMmsoDelta + i];
+    	filteredSegments.forEach(function(mmso) {
     		var mmsostruct = tweetstructure[mmso.id];
     		if (mmsostruct) {
 	    		for (var j = 0; j < topics.length; j++) {
@@ -598,7 +638,7 @@
 					}
 	    		}
     		}
-    	}
+   		});
     	toshow = _(toshow).uniq();
     	    	
     	var tweetstoshow = toshow.map(function(tid) {
@@ -677,7 +717,7 @@
 			h += $(this).outerHeight();
 		});
 		$(".play-localtweets .tweet").css("margin-top",Math.max(0,($(".play-bottom").height() - h)/(tweetstoshow.length+1)));
-		showTopicViz();
+		showLocal();
     	
     }
     
@@ -801,23 +841,22 @@
     	
     	var topics = Array.prototype.join.call($(".topic.selected").map(function(){return $(this).attr("data-topic-id")})).split(",");
     	
-    	for (var i = 0; i < localMmsos.length; i++) {
-    		var mmso = data.segments[localMmsoDelta + i];
+    	filteredSegments.forEach(function(mmso) {
     		if (!tweetstructure[mmso.id]) {
     			tweetstructure[mmso.id] = {
     				mmsoid: mmso.id,
-    				mmsoindex: localMmsoDelta + i,
+    				mmsoindex: parseInt(mmso.id.replace(/^\w+_/,'')),
     				status: 0
     			}
     		}
-    	}
+    	});
     	
     	throttledGetTweetIds();
     	throttledShowTweets();
     }
     
     var throttledGetTweets = _.throttle(getLocalTweets, 500),
-    	throttledShowLocal = _.throttle(showLocal, 100);
+    	throttledShowLocal = _.throttle(showLocal, 50);
     
     showTopics(sortedTopics);
     
@@ -840,15 +879,10 @@
    	});
    	player.on("timeupdate", function(t) {
    		playTime.text(secsToString(t));
-   		globalIndic.css("top", yscale * t);
-   		if (localyscale) {
-   			var localy = (+t - localpos + localduration / 2) * localyscale;
-   			localIndic.css("top", localy);
-   		}
     	if (timelock) {
     		localpos = Math.max(localduration / 2, Math.min(data.duration - localduration / 2, t));
-    		throttledShowLocal();
     	}
+    	throttledShowLocal();
    	});
    	
    	$(".play-button").click(function() {
@@ -873,16 +907,16 @@
     $(".topics-list").on("mouseenter", ".topic", function() {
         var el = $(this);
         el.addClass("hover");
-        showTopicViz();
+        throttledShowLocal();
     }).on("mouseleave", ".topic", function() {
         $(this).removeClass("hover");
-        showTopicViz();
+        throttledShowLocal();
     }).on("click", ".topic", function() {
         var el = $(this);
         $(this).toggleClass("selected");
         el.attr("data-timestamp", el.hasClass("selected") ? ++ordertag : 999999);
 		throttledGetTweets();
-		showTopicViz();
+		throttledShowLocal();
     });
 
 	var h = Hammer($(".play-bottom")[0]);
@@ -1048,6 +1082,8 @@
     	return false;
     });
     
+    $(window).on("resize", throttledShowLocal)
+    
     checkOrGoNext();
 }
 
--- a/playscreen-frame.html	Tue Apr 16 18:26:43 2013 +0200
+++ b/playscreen-frame.html	Wed Apr 17 17:10:43 2013 +0200
@@ -45,18 +45,13 @@
             	</div>
                 
                 <div class="play-bottom">
-                    <div class="play-dataviz">
-                        <div class="play-svg"></div>
-                        <div class="play-images"></div>
-	                	<div class="global-position"></div>
-	                	<div class="local-position"></div>
-                    	<ul class="play-localtweets"></ul>
-                    	<ul class="play-tagcloud"></ul>
-                    	<div class="user-tweets">
-                    		<h3 class="user-tweets-head">Tweets par <span class="user-name"></span></h3>
-                    		<ul class="user-tweets-list"></ul>
-                    	</div>
-                    </div>
+                	<canvas class="play-canvas"></canvas>
+                	<ul class="play-localtweets"></ul>
+                	<ul class="play-tagcloud"></ul>
+                	<div class="user-tweets">
+                		<h3 class="user-tweets-head">Tweets par <span class="user-name"></span></h3>
+                		<ul class="user-tweets-list"></ul>
+                	</div>
                 </div>
             </div>
             <a class="tv" href="#">Ouvrir la fenêtre TV</a>
@@ -69,7 +64,6 @@
         <script src="lib/jquery-ui.min.js"></script>
         <script src="lib/jquery.mousewheel.min.js"></script>
         <script src="lib/hammer.min.js"></script>
-        <script src="lib/raphael-min.js"></script>
         <script src="js/playscreen.js"></script>
         <script src="js/remote-player.js"></script>
         <script type="text/javascript" src="http://159.217.144.101:8050/sia-solr/dwr/engine.js"></script>
--- a/playscreen.html	Tue Apr 16 18:26:43 2013 +0200
+++ b/playscreen.html	Wed Apr 17 17:10:43 2013 +0200
@@ -44,10 +44,7 @@
             	</div>
                 
                 <div class="play-bottom">
-                    <div class="play-svg"></div>
-                    <div class="play-images"></div>
-                	<div class="global-position"></div>
-                	<div class="local-position"></div>
+                	<canvas class="play-canvas"></canvas>
                 	<ul class="play-localtweets"></ul>
                 	<ul class="play-tagcloud"></ul>
                 	<div class="user-tweets">
@@ -65,7 +62,6 @@
         <script src="lib/jquery.ui.touch-punch.min.js"></script>
         <script src="lib/jquery.mousewheel.min.js"></script>
         <script src="lib/hammer.min.js"></script>
-        <script src="lib/raphael-min.js"></script>
         <script src="js/remote-player.js"></script>
         <script src="js/playscreen.js"></script>
         <script type="text/javascript" src="http://159.217.144.101:8050/sia-solr/dwr/engine.js"></script>