Skip to content

Commit 23a89a6

Browse files
committed
Consolidate everything into d3.v2.js.
1 parent 224ff06 commit 23a89a6

40 files changed

Lines changed: 14826 additions & 4543 deletions

_includes/Makefile

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,6 @@
11
SRC_FILES = \
2-
../d3.js \
3-
../d3.min.js \
4-
../d3.chart.js \
5-
../d3.chart.min.js \
6-
../d3.csv.js \
7-
../d3.csv.min.js \
8-
../d3.geo.js \
9-
../d3.geo.min.js \
10-
../d3.geom.js \
11-
../d3.geom.min.js \
12-
../d3.layout.js \
13-
../d3.layout.min.js \
14-
../d3.time.js \
15-
../d3.time.min.js
2+
../d3.v2.js \
3+
../d3.v2.min.js
164

175
EX_FILES = \
186
../ex/box.js \
@@ -65,8 +53,8 @@ EX_FILES = \
6553
../ex/population.css
6654

6755
INCLUDE_FILES = \
68-
box.js \
69-
cluster.js \
56+
box.js \
57+
cluster.js \
7058
cartogram.js \
7159
chord.js \
7260
choropleth.js \
@@ -86,12 +74,18 @@ INCLUDE_FILES = \
8674
tree.js \
8775
population.js
8876

89-
.PHONY all: $(SRC_FILES) $(EX_FILES) $(INCLUDE_FILES)
77+
.PHONY all: $(SRC_FILES) $(EX_FILES) $(INCLUDE_FILES) d3.js d3.min.js
9078

9179
$(SRC_FILES):
9280
@rm -rf $@
9381
git cat-file blob master:$(subst ../,,$@) > $@
9482

83+
../d3.js: ../d3.v2.js
84+
cp $^ $@
85+
86+
../d3.min.js: ../d3.v2.min.js
87+
cp $^ $@
88+
9589
../ex/calendar.css:
9690
@rm -rf $@
9791
git cat-file blob master:examples/calendar/calendar.css > $@

_includes/box.js

Lines changed: 299 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ var w = 120,
44
min = Infinity,
55
max = -Infinity;
66

7-
var chart = d3.chart.box()
7+
var chart = boxChart()
88
.whiskers(iqr(1.5))
99
.width(w - m[1] - m[3])
1010
.height(h - m[0] - m[2]);
@@ -66,3 +66,301 @@ function iqr(k) {
6666
return [i, j];
6767
};
6868
}
69+
70+
// Inspired by http://informationandvisualization.de/blog/box-plot
71+
function boxChart() {
72+
var width = 1,
73+
height = 1,
74+
duration = 0,
75+
domain = null,
76+
value = Number,
77+
whiskers = boxWhiskers,
78+
quartiles = boxQuartiles,
79+
tickFormat = null;
80+
81+
// For each small multiple…
82+
function box(g) {
83+
g.each(function(d, i) {
84+
d = d.map(value).sort(d3.ascending);
85+
var g = d3.select(this),
86+
n = d.length,
87+
min = d[0],
88+
max = d[n - 1];
89+
90+
// Compute quartiles. Must return exactly 3 elements.
91+
var quartileData = d.quartiles = quartiles(d);
92+
93+
// Compute whiskers. Must return exactly 2 elements, or null.
94+
var whiskerIndices = whiskers && whiskers.call(this, d, i),
95+
whiskerData = whiskerIndices && whiskerIndices.map(function(i) { return d[i]; });
96+
97+
// Compute outliers. If no whiskers are specified, all data are "outliers".
98+
// We compute the outliers as indices, so that we can join across transitions!
99+
var outlierIndices = whiskerIndices
100+
? d3.range(0, whiskerIndices[0]).concat(d3.range(whiskerIndices[1] + 1, n))
101+
: d3.range(n);
102+
103+
// Compute the new x-scale.
104+
var x1 = d3.scale.linear()
105+
.domain(domain && domain.call(this, d, i) || [min, max])
106+
.range([height, 0]);
107+
108+
// Retrieve the old x-scale, if this is an update.
109+
var x0 = this.__chart__ || d3.scale.linear()
110+
.domain([0, Infinity])
111+
.range(x1.range());
112+
113+
// Stash the new scale.
114+
this.__chart__ = x1;
115+
116+
// Note: the box, median, and box tick elements are fixed in number,
117+
// so we only have to handle enter and update. In contrast, the outliers
118+
// and other elements are variable, so we need to exit them! Variable
119+
// elements also fade in and out.
120+
121+
// Update center line: the vertical line spanning the whiskers.
122+
var center = g.selectAll("line.center")
123+
.data(whiskerData ? [whiskerData] : []);
124+
125+
center.enter().insert("svg:line", "rect")
126+
.attr("class", "center")
127+
.attr("x1", width / 2)
128+
.attr("y1", function(d) { return x0(d[0]); })
129+
.attr("x2", width / 2)
130+
.attr("y2", function(d) { return x0(d[1]); })
131+
.style("opacity", 1e-6)
132+
.transition()
133+
.duration(duration)
134+
.style("opacity", 1)
135+
.attr("y1", function(d) { return x1(d[0]); })
136+
.attr("y2", function(d) { return x1(d[1]); });
137+
138+
center.transition()
139+
.duration(duration)
140+
.style("opacity", 1)
141+
.attr("y1", function(d) { return x1(d[0]); })
142+
.attr("y2", function(d) { return x1(d[1]); });
143+
144+
center.exit().transition()
145+
.duration(duration)
146+
.style("opacity", 1e-6)
147+
.attr("y1", function(d) { return x1(d[0]); })
148+
.attr("y2", function(d) { return x1(d[1]); })
149+
.remove();
150+
151+
// Update innerquartile box.
152+
var box = g.selectAll("rect.box")
153+
.data([quartileData]);
154+
155+
box.enter().append("svg:rect")
156+
.attr("class", "box")
157+
.attr("x", 0)
158+
.attr("y", function(d) { return x0(d[2]); })
159+
.attr("width", width)
160+
.attr("height", function(d) { return x0(d[0]) - x0(d[2]); })
161+
.transition()
162+
.duration(duration)
163+
.attr("y", function(d) { return x1(d[2]); })
164+
.attr("height", function(d) { return x1(d[0]) - x1(d[2]); });
165+
166+
box.transition()
167+
.duration(duration)
168+
.attr("y", function(d) { return x1(d[2]); })
169+
.attr("height", function(d) { return x1(d[0]) - x1(d[2]); });
170+
171+
// Update median line.
172+
var medianLine = g.selectAll("line.median")
173+
.data([quartileData[1]]);
174+
175+
medianLine.enter().append("svg:line")
176+
.attr("class", "median")
177+
.attr("x1", 0)
178+
.attr("y1", x0)
179+
.attr("x2", width)
180+
.attr("y2", x0)
181+
.transition()
182+
.duration(duration)
183+
.attr("y1", x1)
184+
.attr("y2", x1);
185+
186+
medianLine.transition()
187+
.duration(duration)
188+
.attr("y1", x1)
189+
.attr("y2", x1);
190+
191+
// Update whiskers.
192+
var whisker = g.selectAll("line.whisker")
193+
.data(whiskerData || []);
194+
195+
whisker.enter().insert("svg:line", "circle, text")
196+
.attr("class", "whisker")
197+
.attr("x1", 0)
198+
.attr("y1", x0)
199+
.attr("x2", width)
200+
.attr("y2", x0)
201+
.style("opacity", 1e-6)
202+
.transition()
203+
.duration(duration)
204+
.attr("y1", x1)
205+
.attr("y2", x1)
206+
.style("opacity", 1);
207+
208+
whisker.transition()
209+
.duration(duration)
210+
.attr("y1", x1)
211+
.attr("y2", x1)
212+
.style("opacity", 1);
213+
214+
whisker.exit().transition()
215+
.duration(duration)
216+
.attr("y1", x1)
217+
.attr("y2", x1)
218+
.style("opacity", 1e-6)
219+
.remove();
220+
221+
// Update outliers.
222+
var outlier = g.selectAll("circle.outlier")
223+
.data(outlierIndices, Number);
224+
225+
outlier.enter().insert("svg:circle", "text")
226+
.attr("class", "outlier")
227+
.attr("r", 5)
228+
.attr("cx", width / 2)
229+
.attr("cy", function(i) { return x0(d[i]); })
230+
.style("opacity", 1e-6)
231+
.transition()
232+
.duration(duration)
233+
.attr("cy", function(i) { return x1(d[i]); })
234+
.style("opacity", 1);
235+
236+
outlier.transition()
237+
.duration(duration)
238+
.attr("cy", function(i) { return x1(d[i]); })
239+
.style("opacity", 1);
240+
241+
outlier.exit().transition()
242+
.duration(duration)
243+
.attr("cy", function(i) { return x1(d[i]); })
244+
.style("opacity", 1e-6)
245+
.remove();
246+
247+
// Compute the tick format.
248+
var format = tickFormat || x1.tickFormat(8);
249+
250+
// Update box ticks.
251+
var boxTick = g.selectAll("text.box")
252+
.data(quartileData);
253+
254+
boxTick.enter().append("svg:text")
255+
.attr("class", "box")
256+
.attr("dy", ".3em")
257+
.attr("dx", function(d, i) { return i & 1 ? 6 : -6 })
258+
.attr("x", function(d, i) { return i & 1 ? width : 0 })
259+
.attr("y", x0)
260+
.attr("text-anchor", function(d, i) { return i & 1 ? "start" : "end"; })
261+
.text(format)
262+
.transition()
263+
.duration(duration)
264+
.attr("y", x1);
265+
266+
boxTick.transition()
267+
.duration(duration)
268+
.text(format)
269+
.attr("y", x1);
270+
271+
// Update whisker ticks. These are handled separately from the box
272+
// ticks because they may or may not exist, and we want don't want
273+
// to join box ticks pre-transition with whisker ticks post-.
274+
var whiskerTick = g.selectAll("text.whisker")
275+
.data(whiskerData || []);
276+
277+
whiskerTick.enter().append("svg:text")
278+
.attr("class", "whisker")
279+
.attr("dy", ".3em")
280+
.attr("dx", 6)
281+
.attr("x", width)
282+
.attr("y", x0)
283+
.text(format)
284+
.style("opacity", 1e-6)
285+
.transition()
286+
.duration(duration)
287+
.attr("y", x1)
288+
.style("opacity", 1);
289+
290+
whiskerTick.transition()
291+
.duration(duration)
292+
.text(format)
293+
.attr("y", x1)
294+
.style("opacity", 1);
295+
296+
whiskerTick.exit().transition()
297+
.duration(duration)
298+
.attr("y", x1)
299+
.style("opacity", 1e-6)
300+
.remove();
301+
});
302+
d3.timer.flush();
303+
}
304+
305+
box.width = function(x) {
306+
if (!arguments.length) return width;
307+
width = x;
308+
return box;
309+
};
310+
311+
box.height = function(x) {
312+
if (!arguments.length) return height;
313+
height = x;
314+
return box;
315+
};
316+
317+
box.tickFormat = function(x) {
318+
if (!arguments.length) return tickFormat;
319+
tickFormat = x;
320+
return box;
321+
};
322+
323+
box.duration = function(x) {
324+
if (!arguments.length) return duration;
325+
duration = x;
326+
return box;
327+
};
328+
329+
box.domain = function(x) {
330+
if (!arguments.length) return domain;
331+
domain = x == null ? x : d3.functor(x);
332+
return box;
333+
};
334+
335+
box.value = function(x) {
336+
if (!arguments.length) return value;
337+
value = x;
338+
return box;
339+
};
340+
341+
box.whiskers = function(x) {
342+
if (!arguments.length) return whiskers;
343+
whiskers = x;
344+
return box;
345+
};
346+
347+
box.quartiles = function(x) {
348+
if (!arguments.length) return quartiles;
349+
quartiles = x;
350+
return box;
351+
};
352+
353+
return box;
354+
};
355+
356+
function boxWhiskers(d) {
357+
return [0, d.length - 1];
358+
}
359+
360+
function boxQuartiles(d) {
361+
return [
362+
d3.quantile(d, .25),
363+
d3.quantile(d, .5),
364+
d3.quantile(d, .75)
365+
];
366+
}

0 commit comments

Comments
 (0)