1 function Streamgraph($selector) { |
1 function Streamgraph($selector, data/*, data2*/) |
|
2 { |
2 |
3 |
3 /* Constants */ |
4 /* Constants */ |
4 |
5 |
5 var VMARGIN = 3, |
6 var VMARGIN = 3, |
6 YEARSHEIGHT = 20, |
7 YEARSHEIGHT = 20, |
7 STARTTIME = new Date(2007,6,1), |
8 STARTTIME = new Date(data.from_date), |
8 ENDTIME = new Date(), |
9 ENDTIME = new Date(data.to_date), |
|
10 DATASTART = new Date(data.from_date), |
|
11 DATAEND = new Date(data.to_date), |
9 CURVE = .25, |
12 CURVE = .25, |
10 DATEPADDING = 10, |
13 DATEPADDING = 10, |
11 COLORS = [ "#943a23", "#fbee97", "#cfbb95", "#da9761", "#ba5036" ], |
14 COLORS = [ "#51585E", "#12161C", "#457DAD", "#899DAA", "#0781BD" ], |
|
15 QUERYID = data.query_id, |
12 SELECTEDCOLOR = "#c51810"; |
16 SELECTEDCOLOR = "#c51810"; |
13 |
17 |
14 /* Generating random data */ |
|
15 |
|
16 var data = [], |
|
17 clustercount = 12, |
|
18 slicecount = 20, |
|
19 maxdata = 10, |
|
20 randpart = 4, |
|
21 dampfactor = .333; |
|
22 for (var i = 0; i < clustercount; i++) { |
|
23 var line = [], |
|
24 peaktime = Math.floor(Math.random() * slicecount); |
|
25 for (var j = 0; j < slicecount; j++) { |
|
26 var point = Math.min(maxdata, Math.max(0, (Math.random() - .5) * randpart + Math.max(0, maxdata * (1 - dampfactor * Math.abs(j - peaktime))))); |
|
27 line.push(point); |
|
28 } |
|
29 data.push(line); |
|
30 } |
|
31 |
|
32 /* Calculating scales and positions */ |
18 /* Calculating scales and positions */ |
33 |
19 |
34 var width = $selector.width(), |
20 var width = $selector.width(), |
35 height = $selector.height(), |
21 height = $selector.height(), |
36 transp = _.zip.apply( _, data ), |
22 transp = _.zip.apply( _, _(data.clusters).pluck("volumes") ), |
37 cumulative = _(transp).map(function(column) { |
23 cumulative = _(transp).map(function(column) { |
38 var total = 0; |
24 var total = 0; |
39 return _(column).map(function(point) { |
25 return _(column).map(function(point) { |
40 return total += point; |
26 return total += point; |
41 }); |
27 }); |
43 sums = _(cumulative).map(function(column) { |
29 sums = _(cumulative).map(function(column) { |
44 return _(column).last(); |
30 return _(column).last(); |
45 }) |
31 }) |
46 maxcol = _(sums).max(), |
32 maxcol = _(sums).max(), |
47 streamheight = height - YEARSHEIGHT, |
33 streamheight = height - YEARSHEIGHT, |
|
34 streamwidth = width * (DATAEND - DATASTART) / (ENDTIME - STARTTIME), |
48 yscale = (streamheight - 2 * VMARGIN) / maxcol, |
35 yscale = (streamheight - 2 * VMARGIN) / maxcol, |
49 centery = streamheight / 2, |
36 centery = streamheight / 2, |
50 xscale = width / (transp.length - 1), |
37 xscale = streamwidth / (transp.length - 1), |
51 txscale = width / (ENDTIME - STARTTIME), |
38 txscale = width / (ENDTIME - STARTTIME), |
52 coords = _(data).map(function(line, lineindex) { |
39 startx = txscale * (DATASTART - STARTTIME), |
|
40 endx = txscale * (DATAEND - STARTTIME), |
|
41 coords = _(data.clusters).map(function(line, lineindex) { |
53 return { |
42 return { |
54 points : _(line).map(function(point, colindex) { |
43 points : _(line.volumes).map(function(point, colindex) { |
55 var lowercumul = lineindex ? cumulative[colindex][lineindex - 1] : 0, |
44 var lowercumul = lineindex ? cumulative[colindex][lineindex - 1] : 0, |
56 uppercumul = cumulative[colindex][lineindex]; |
45 uppercumul = cumulative[colindex][lineindex]; |
57 return { |
46 return { |
58 data: point, |
47 data: point, |
59 x: xscale * colindex, |
48 x: startx + xscale * colindex, |
60 lowery: centery + yscale * ( ( sums[colindex] / 2 ) - lowercumul ), |
49 lowery: centery + yscale * ( ( sums[colindex] / 2 ) - lowercumul ), |
61 uppery: centery + yscale * ( ( sums[colindex] / 2 ) - uppercumul ), |
50 uppery: centery + yscale * ( ( sums[colindex] / 2 ) - uppercumul ), |
62 } |
51 } |
63 }) |
52 }), |
|
53 id : line.id, |
|
54 title: line.title |
64 } |
55 } |
65 }), |
56 }), |
66 _(coords).each(function(line) { |
57 _(coords).each(function(line) { |
67 var lowerline = _(line.points).reduce(function(path, point, colindex) { |
58 var lowerline = _(line.points).reduce(function(path, point, colindex) { |
68 var res = path; |
59 var res = path; |
91 line.path = lowerline + upperline; |
82 line.path = lowerline + upperline; |
92 }); |
83 }); |
93 |
84 |
94 /* Drawing streamgraph*/ |
85 /* Drawing streamgraph*/ |
95 |
86 |
|
87 $selector.empty(); |
|
88 |
96 var paper = new Raphael($selector[0]); |
89 var paper = new Raphael($selector[0]); |
|
90 |
|
91 paper.path("M0 " + (1+centery) + "L" + width + " " + (1+centery)).attr({ |
|
92 stroke: "#000" |
|
93 }) |
97 |
94 |
98 _(coords).each(function(line, index) { |
95 _(coords).each(function(line, index) { |
99 line.color = COLORS[index % COLORS.length]; |
96 line.color = COLORS[index % COLORS.length]; |
|
97 //var hue = (parseInt(line.id)%6)/6; |
|
98 //line.color = Raphael.hsl( hue, 1, .8 ); |
|
99 //line.highlightColor = Raphael.hsl( hue, 1, .4 ); |
100 line.surface = paper.path(line.path); |
100 line.surface = paper.path(line.path); |
101 line.surface.attr({ |
101 line.surface.attr({ |
102 stroke: "none", |
102 stroke: "#ffffff", |
|
103 "stroke-width": .25, |
103 fill: line.color |
104 fill: line.color |
104 }); |
105 }); |
105 }); |
106 }); |
106 |
107 |
107 /* Drawing years */ |
108 /* Drawing years */ |
125 var carregauche = paper.rect(width,-1,width,(2+height)), |
126 var carregauche = paper.rect(width,-1,width,(2+height)), |
126 carredroite = paper.rect(-width,-1,width,(2+height)), |
127 carredroite = paper.rect(-width,-1,width,(2+height)), |
127 attrcarres = { |
128 attrcarres = { |
128 fill: "#333333", |
129 fill: "#333333", |
129 "fill-opacity": .5, |
130 "fill-opacity": .5, |
130 stroke: SELECTEDCOLOR |
131 stroke: "#c51810" |
131 }; |
132 }; |
132 carregauche.attr(attrcarres); |
133 carregauche.attr(attrcarres); |
133 carredroite.attr(attrcarres); |
134 carredroite.attr(attrcarres); |
134 |
135 |
135 var rangerect = paper.rect(0, (height - YEARSHEIGHT), width, YEARSHEIGHT); |
136 var rangerect = paper.rect(0, (height - YEARSHEIGHT), width, YEARSHEIGHT); |
136 rangerect.attr({ |
137 rangerect.attr({ |
137 fill: SELECTEDCOLOR, |
138 fill: "#c51810", |
138 stroke: "none" |
139 stroke: "none" |
139 }); |
140 }); |
140 |
141 |
141 function datetext(date) { |
142 function datetext(date) { |
142 var d = new Date(date), |
143 var d = new Date(date), |
155 fill: "#ffffff", |
156 fill: "#ffffff", |
156 "text-anchor": "end" |
157 "text-anchor": "end" |
157 }); |
158 }); |
158 |
159 |
159 /* Redrawing time slices for rollover effect */ |
160 /* Redrawing time slices for rollover effect */ |
160 |
161 var mem = ''; |
161 _(coords).each(function(line, index) { |
162 _(coords).each(function(line, index) { |
162 line.mousesurface = paper.path(line.path); |
163 line.mousesurface = paper.path(line.path); |
163 console.log(line.mousesurface); |
164 mem += '<li><a href="http://localhost:8000/'+QUERYID+'/'+line.id+'/0/12/0" title="Afficher le cluster" data-cluster-id="' + line.id + '">' + line.title + '</a></li>'; |
164 line.mousesurface.attr({ |
165 line.mousesurface.attr({ |
165 stroke: "none", |
166 stroke: "none", |
166 fill: line.color, |
167 fill: line.color, |
167 opacity: .01 |
168 opacity: .01, |
|
169 title: line.title, |
|
170 href: "http://localhost:8000/"+QUERYID+"/"+line.id+"/0/12/0" |
168 }).mouseover(function() { |
171 }).mouseover(function() { |
169 line.surface.attr({ |
172 //alert('mousse select'); |
170 fill: SELECTEDCOLOR |
173 $("body").trigger("select-cluster", line.id); |
171 }) |
|
172 }).mouseout(function() { |
174 }).mouseout(function() { |
|
175 //alert('mousse unselect'); |
|
176 $("body").trigger("unselect-cluster", line.id); |
|
177 |
|
178 }); |
|
179 // $(line.mousesurface.node).attr("data-cluster-id", line.id).parent().attr("data-cluster-id", line.id); |
|
180 }); |
|
181 |
|
182 $(".cluster").html(mem) ; |
|
183 /* if (typeof (data2) != 'undefined') |
|
184 { |
|
185 // alert('dat2not null'); |
|
186 |
|
187 |
|
188 |
|
189 var line = _(coords).find(function(line) |
|
190 { |
|
191 return line.id == 1; |
|
192 }); |
|
193 //alert(line.id); |
|
194 if (line) |
|
195 { |
|
196 alert(line.id); |
|
197 line.surface.attr({ fill: SELECTEDCOLOR }); |
|
198 } |
|
199 |
|
200 |
|
201 } |
|
202 else |
|
203 { |
|
204 alert('dat2 null'); |
|
205 }*/ |
|
206 $(".actu, .cluster a, .article").hover |
|
207 ( |
|
208 function() { |
|
209 $("body").trigger("select-cluster", $(this).attr("data-cluster-id")); |
|
210 }, |
|
211 function() { |
|
212 $("body").trigger("unselect-cluster", $(this).attr("data-cluster-id")); |
|
213 } |
|
214 ) |
|
215 |
|
216 $("body").on("unselect-cluster", function(e, clusterid) { |
|
217 $(".actu[data-cluster-id='" + clusterid + "'], .cluster a[data-cluster-id='" + clusterid + "'], .article[data-cluster-id='" + clusterid + "']").removeClass("selected"); |
|
218 var line = _(coords).find(function(line) { |
|
219 return line.id == clusterid; |
|
220 }); |
|
221 if (line) { |
173 line.surface.attr({ |
222 line.surface.attr({ |
174 fill: line.color |
223 fill: line.color |
175 }) |
224 }); |
176 }); |
225 } |
177 }); |
226 }); |
|
227 |
|
228 |
|
229 |
|
230 $("body").on("select-cluster", function(e, clusterid) { |
|
231 $(".actu[data-cluster-id='" + clusterid + "'], .cluster a[data-cluster-id='" + clusterid + "'], .article[data-cluster-id='" + clusterid + "']").addClass("selected"); |
|
232 var line = _(coords).find(function(line) { |
|
233 return line.id == clusterid; |
|
234 }); |
|
235 if (line) { |
|
236 line.surface.attr({ |
|
237 fill: SELECTEDCOLOR //line.highlightColor |
|
238 }); |
|
239 } |
|
240 }); |
|
241 |
|
242 /*$("body").on("select-cluster", function(e, clusterid) |
|
243 { |
|
244 $(".actu[data-cluster-id='" + clusterid + "'], .cluster a[data-cluster-id='" + clusterid + "'], .article[data-cluster-id='" + clusterid + "']").addClass("selected"); |
|
245 }); |
|
246 $("body").on("unselect-cluster", function(e, clusterid) { |
|
247 $(".actu[data-cluster-id='" + clusterid + "'], .cluster a[data-cluster-id='" + clusterid + "'], .article[data-cluster-id='" + clusterid + "']").removeClass("selected"); |
|
248 });*/ |
178 |
249 |
179 /* Returning a handler for slide value change */ |
250 /* Returning a handler for slide value change */ |
180 |
251 |
181 this.slidevalues = function(left, right) { |
252 this.slidevalues = function(left, right) { |
182 left = left || 0; |
253 left = left || 0; |
194 rangerect.attr({ |
265 rangerect.attr({ |
195 x: left, |
266 x: left, |
196 width: right - left |
267 width: right - left |
197 }); |
268 }); |
198 } |
269 } |
|
270 |
|
271 $("#slider-range").dragslider("values", [startx, endx]); |
|
272 this.slidevalues(startx, endx); |
199 |
273 |
200 } |
274 } |
201 |
275 |
202 $(function() { |
276 function loadStreamgraph(data/*,data2*/) { |
203 window.streamgraph = new Streamgraph($(".streamgraph")); |
277 |
204 streamgraph.slidevalues.apply(streamgraph,$("#slider-range").dragslider("values")); |
278 $(".streamgraph").empty(); |
205 }) |
279 delete window.streamgraph; |
|
280 |
|
281 //$.getJSON(url, function(data) { |
|
282 window.streamgraph = new Streamgraph($(".streamgraph"), data/*,data2*/); |
|
283 streamgraph.slidevalues.apply(streamgraph,$("#slider-range").dragslider("values")); |
|
284 |
|
285 //}); |
|
286 } |
|
287 |
|
288 /*$(function() { |
|
289 loadStreamgraph("data/json_streamgraph.json"); |
|
290 })*/ |