d3_rails 2.7.4 → 2.7.5.v2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.DS_Store +0 -0
- data/README.md +16 -2
- data/lib/d3_rails/version.rb +1 -1
- data/vendor/.DS_Store +0 -0
- data/vendor/assets/javascripts/LICENSE +12 -13
- data/vendor/assets/javascripts/chart/box.js +297 -0
- data/vendor/assets/javascripts/chart/bullet.js +237 -0
- data/vendor/assets/javascripts/chart/chart.js +1 -0
- data/vendor/assets/javascripts/chart/horizon.js +203 -0
- data/vendor/assets/javascripts/chart/qq.js +245 -0
- data/vendor/assets/javascripts/d3.chart.js +0 -0
- data/vendor/assets/javascripts/d3.geo.js +0 -0
- data/vendor/assets/javascripts/d3.geom.js +0 -0
- data/vendor/assets/javascripts/d3.js +21 -18
- data/vendor/assets/javascripts/d3.layout.js +5 -4
- data/vendor/assets/javascripts/d3.time.js +0 -0
- data/vendor/assets/javascripts/d3_chart_module.js +1 -0
- data/vendor/assets/javascripts/d3_csv.js +0 -0
- data/vendor/assets/javascripts/d3_rails.js +1 -1
- metadata +18 -12
- data/vendor/assets/javascripts/package.json +0 -33
data/.DS_Store
CHANGED
Binary file
|
data/README.md
CHANGED
@@ -14,8 +14,8 @@ or you can use it to build dynamic pages (like jQuery).
|
|
14
14
|
|
15
15
|
# D3 Version
|
16
16
|
|
17
|
-
The current release of this gem is using **D3 v=2.7.
|
18
|
-
**Last Updated 2-
|
17
|
+
The current release of this gem is using **D3 v=2.7.5**
|
18
|
+
**Last Updated 2-21-2012**
|
19
19
|
|
20
20
|
# Included Javascripts
|
21
21
|
**minified js files are not included, since the rails asset pipeline sorta necessitates the compiling (and likely minifying) your js files for production**
|
@@ -32,6 +32,20 @@ The current release of this gem is using **D3 v=2.7.4**
|
|
32
32
|
science.lin.js
|
33
33
|
science.stats.js
|
34
34
|
|
35
|
+
# D3 charting module
|
36
|
+
|
37
|
+
** D3 charts can be be included in your rails application by including the following line in your javascripts manifest **
|
38
|
+
|
39
|
+
//= require d3_chart_module
|
40
|
+
|
41
|
+
This will include the following javascripts to your application:
|
42
|
+
|
43
|
+
box.js
|
44
|
+
bullet.js
|
45
|
+
chart.js
|
46
|
+
horizon.js
|
47
|
+
qq.js
|
48
|
+
|
35
49
|
### Installation
|
36
50
|
|
37
51
|
This gem should work out of the box. All you have to do is add the gem to your Gemfile:
|
data/lib/d3_rails/version.rb
CHANGED
data/vendor/.DS_Store
ADDED
Binary file
|
@@ -1,5 +1,5 @@
|
|
1
|
-
Copyright (c) 2010,
|
2
|
-
All rights reserved
|
1
|
+
Copyright (c) 2010, Michael Bostock
|
2
|
+
All rights reserved.
|
3
3
|
|
4
4
|
Redistribution and use in source and binary forms, with or without
|
5
5
|
modification, are permitted provided that the following conditions are met:
|
@@ -11,17 +11,16 @@ modification, are permitted provided that the following conditions are met:
|
|
11
11
|
this list of conditions and the following disclaimer in the documentation
|
12
12
|
and/or other materials provided with the distribution.
|
13
13
|
|
14
|
-
*
|
15
|
-
|
16
|
-
specific prior written permission.
|
14
|
+
* The name Michael Bostock may not be used to endorse or promote products
|
15
|
+
derived from this software without specific prior written permission.
|
17
16
|
|
18
|
-
THIS SOFTWARE IS PROVIDED BY
|
19
|
-
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
20
|
-
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
21
|
-
EVENT SHALL
|
22
|
-
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
23
|
-
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
24
|
-
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
25
|
-
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
17
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
+
DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
|
21
|
+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
22
|
+
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
23
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
24
|
+
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
26
25
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
27
26
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@@ -0,0 +1,297 @@
|
|
1
|
+
// Inspired by http://informationandvisualization.de/blog/box-plot
|
2
|
+
d3.chart.box = function() {
|
3
|
+
var width = 1,
|
4
|
+
height = 1,
|
5
|
+
duration = 0,
|
6
|
+
domain = null,
|
7
|
+
value = Number,
|
8
|
+
whiskers = d3_chart_boxWhiskers,
|
9
|
+
quartiles = d3_chart_boxQuartiles,
|
10
|
+
tickFormat = null;
|
11
|
+
|
12
|
+
// For each small multiple…
|
13
|
+
function box(g) {
|
14
|
+
g.each(function(d, i) {
|
15
|
+
d = d.map(value).sort(d3.ascending);
|
16
|
+
var g = d3.select(this),
|
17
|
+
n = d.length,
|
18
|
+
min = d[0],
|
19
|
+
max = d[n - 1];
|
20
|
+
|
21
|
+
// Compute quartiles. Must return exactly 3 elements.
|
22
|
+
var quartileData = d.quartiles = quartiles(d);
|
23
|
+
|
24
|
+
// Compute whiskers. Must return exactly 2 elements, or null.
|
25
|
+
var whiskerIndices = whiskers && whiskers.call(this, d, i),
|
26
|
+
whiskerData = whiskerIndices && whiskerIndices.map(function(i) { return d[i]; });
|
27
|
+
|
28
|
+
// Compute outliers. If no whiskers are specified, all data are "outliers".
|
29
|
+
// We compute the outliers as indices, so that we can join across transitions!
|
30
|
+
var outlierIndices = whiskerIndices
|
31
|
+
? d3.range(0, whiskerIndices[0]).concat(d3.range(whiskerIndices[1] + 1, n))
|
32
|
+
: d3.range(n);
|
33
|
+
|
34
|
+
// Compute the new x-scale.
|
35
|
+
var x1 = d3.scale.linear()
|
36
|
+
.domain(domain && domain.call(this, d, i) || [min, max])
|
37
|
+
.range([height, 0]);
|
38
|
+
|
39
|
+
// Retrieve the old x-scale, if this is an update.
|
40
|
+
var x0 = this.__chart__ || d3.scale.linear()
|
41
|
+
.domain([0, Infinity])
|
42
|
+
.range(x1.range());
|
43
|
+
|
44
|
+
// Stash the new scale.
|
45
|
+
this.__chart__ = x1;
|
46
|
+
|
47
|
+
// Note: the box, median, and box tick elements are fixed in number,
|
48
|
+
// so we only have to handle enter and update. In contrast, the outliers
|
49
|
+
// and other elements are variable, so we need to exit them! Variable
|
50
|
+
// elements also fade in and out.
|
51
|
+
|
52
|
+
// Update center line: the vertical line spanning the whiskers.
|
53
|
+
var center = g.selectAll("line.center")
|
54
|
+
.data(whiskerData ? [whiskerData] : []);
|
55
|
+
|
56
|
+
center.enter().insert("svg:line", "rect")
|
57
|
+
.attr("class", "center")
|
58
|
+
.attr("x1", width / 2)
|
59
|
+
.attr("y1", function(d) { return x0(d[0]); })
|
60
|
+
.attr("x2", width / 2)
|
61
|
+
.attr("y2", function(d) { return x0(d[1]); })
|
62
|
+
.style("opacity", 1e-6)
|
63
|
+
.transition()
|
64
|
+
.duration(duration)
|
65
|
+
.style("opacity", 1)
|
66
|
+
.attr("y1", function(d) { return x1(d[0]); })
|
67
|
+
.attr("y2", function(d) { return x1(d[1]); });
|
68
|
+
|
69
|
+
center.transition()
|
70
|
+
.duration(duration)
|
71
|
+
.style("opacity", 1)
|
72
|
+
.attr("y1", function(d) { return x1(d[0]); })
|
73
|
+
.attr("y2", function(d) { return x1(d[1]); });
|
74
|
+
|
75
|
+
center.exit().transition()
|
76
|
+
.duration(duration)
|
77
|
+
.style("opacity", 1e-6)
|
78
|
+
.attr("y1", function(d) { return x1(d[0]); })
|
79
|
+
.attr("y2", function(d) { return x1(d[1]); })
|
80
|
+
.remove();
|
81
|
+
|
82
|
+
// Update innerquartile box.
|
83
|
+
var box = g.selectAll("rect.box")
|
84
|
+
.data([quartileData]);
|
85
|
+
|
86
|
+
box.enter().append("svg:rect")
|
87
|
+
.attr("class", "box")
|
88
|
+
.attr("x", 0)
|
89
|
+
.attr("y", function(d) { return x0(d[2]); })
|
90
|
+
.attr("width", width)
|
91
|
+
.attr("height", function(d) { return x0(d[0]) - x0(d[2]); })
|
92
|
+
.transition()
|
93
|
+
.duration(duration)
|
94
|
+
.attr("y", function(d) { return x1(d[2]); })
|
95
|
+
.attr("height", function(d) { return x1(d[0]) - x1(d[2]); });
|
96
|
+
|
97
|
+
box.transition()
|
98
|
+
.duration(duration)
|
99
|
+
.attr("y", function(d) { return x1(d[2]); })
|
100
|
+
.attr("height", function(d) { return x1(d[0]) - x1(d[2]); });
|
101
|
+
|
102
|
+
// Update median line.
|
103
|
+
var medianLine = g.selectAll("line.median")
|
104
|
+
.data([quartileData[1]]);
|
105
|
+
|
106
|
+
medianLine.enter().append("svg:line")
|
107
|
+
.attr("class", "median")
|
108
|
+
.attr("x1", 0)
|
109
|
+
.attr("y1", x0)
|
110
|
+
.attr("x2", width)
|
111
|
+
.attr("y2", x0)
|
112
|
+
.transition()
|
113
|
+
.duration(duration)
|
114
|
+
.attr("y1", x1)
|
115
|
+
.attr("y2", x1);
|
116
|
+
|
117
|
+
medianLine.transition()
|
118
|
+
.duration(duration)
|
119
|
+
.attr("y1", x1)
|
120
|
+
.attr("y2", x1);
|
121
|
+
|
122
|
+
// Update whiskers.
|
123
|
+
var whisker = g.selectAll("line.whisker")
|
124
|
+
.data(whiskerData || []);
|
125
|
+
|
126
|
+
whisker.enter().insert("svg:line", "circle, text")
|
127
|
+
.attr("class", "whisker")
|
128
|
+
.attr("x1", 0)
|
129
|
+
.attr("y1", x0)
|
130
|
+
.attr("x2", width)
|
131
|
+
.attr("y2", x0)
|
132
|
+
.style("opacity", 1e-6)
|
133
|
+
.transition()
|
134
|
+
.duration(duration)
|
135
|
+
.attr("y1", x1)
|
136
|
+
.attr("y2", x1)
|
137
|
+
.style("opacity", 1);
|
138
|
+
|
139
|
+
whisker.transition()
|
140
|
+
.duration(duration)
|
141
|
+
.attr("y1", x1)
|
142
|
+
.attr("y2", x1)
|
143
|
+
.style("opacity", 1);
|
144
|
+
|
145
|
+
whisker.exit().transition()
|
146
|
+
.duration(duration)
|
147
|
+
.attr("y1", x1)
|
148
|
+
.attr("y2", x1)
|
149
|
+
.style("opacity", 1e-6)
|
150
|
+
.remove();
|
151
|
+
|
152
|
+
// Update outliers.
|
153
|
+
var outlier = g.selectAll("circle.outlier")
|
154
|
+
.data(outlierIndices, Number);
|
155
|
+
|
156
|
+
outlier.enter().insert("svg:circle", "text")
|
157
|
+
.attr("class", "outlier")
|
158
|
+
.attr("r", 5)
|
159
|
+
.attr("cx", width / 2)
|
160
|
+
.attr("cy", function(i) { return x0(d[i]); })
|
161
|
+
.style("opacity", 1e-6)
|
162
|
+
.transition()
|
163
|
+
.duration(duration)
|
164
|
+
.attr("cy", function(i) { return x1(d[i]); })
|
165
|
+
.style("opacity", 1);
|
166
|
+
|
167
|
+
outlier.transition()
|
168
|
+
.duration(duration)
|
169
|
+
.attr("cy", function(i) { return x1(d[i]); })
|
170
|
+
.style("opacity", 1);
|
171
|
+
|
172
|
+
outlier.exit().transition()
|
173
|
+
.duration(duration)
|
174
|
+
.attr("cy", function(i) { return x1(d[i]); })
|
175
|
+
.style("opacity", 1e-6)
|
176
|
+
.remove();
|
177
|
+
|
178
|
+
// Compute the tick format.
|
179
|
+
var format = tickFormat || x1.tickFormat(8);
|
180
|
+
|
181
|
+
// Update box ticks.
|
182
|
+
var boxTick = g.selectAll("text.box")
|
183
|
+
.data(quartileData);
|
184
|
+
|
185
|
+
boxTick.enter().append("svg:text")
|
186
|
+
.attr("class", "box")
|
187
|
+
.attr("dy", ".3em")
|
188
|
+
.attr("dx", function(d, i) { return i & 1 ? 6 : -6 })
|
189
|
+
.attr("x", function(d, i) { return i & 1 ? width : 0 })
|
190
|
+
.attr("y", x0)
|
191
|
+
.attr("text-anchor", function(d, i) { return i & 1 ? "start" : "end"; })
|
192
|
+
.text(format)
|
193
|
+
.transition()
|
194
|
+
.duration(duration)
|
195
|
+
.attr("y", x1);
|
196
|
+
|
197
|
+
boxTick.transition()
|
198
|
+
.duration(duration)
|
199
|
+
.text(format)
|
200
|
+
.attr("y", x1);
|
201
|
+
|
202
|
+
// Update whisker ticks. These are handled separately from the box
|
203
|
+
// ticks because they may or may not exist, and we want don't want
|
204
|
+
// to join box ticks pre-transition with whisker ticks post-.
|
205
|
+
var whiskerTick = g.selectAll("text.whisker")
|
206
|
+
.data(whiskerData || []);
|
207
|
+
|
208
|
+
whiskerTick.enter().append("svg:text")
|
209
|
+
.attr("class", "whisker")
|
210
|
+
.attr("dy", ".3em")
|
211
|
+
.attr("dx", 6)
|
212
|
+
.attr("x", width)
|
213
|
+
.attr("y", x0)
|
214
|
+
.text(format)
|
215
|
+
.style("opacity", 1e-6)
|
216
|
+
.transition()
|
217
|
+
.duration(duration)
|
218
|
+
.attr("y", x1)
|
219
|
+
.style("opacity", 1);
|
220
|
+
|
221
|
+
whiskerTick.transition()
|
222
|
+
.duration(duration)
|
223
|
+
.text(format)
|
224
|
+
.attr("y", x1)
|
225
|
+
.style("opacity", 1);
|
226
|
+
|
227
|
+
whiskerTick.exit().transition()
|
228
|
+
.duration(duration)
|
229
|
+
.attr("y", x1)
|
230
|
+
.style("opacity", 1e-6)
|
231
|
+
.remove();
|
232
|
+
});
|
233
|
+
d3.timer.flush();
|
234
|
+
}
|
235
|
+
|
236
|
+
box.width = function(x) {
|
237
|
+
if (!arguments.length) return width;
|
238
|
+
width = x;
|
239
|
+
return box;
|
240
|
+
};
|
241
|
+
|
242
|
+
box.height = function(x) {
|
243
|
+
if (!arguments.length) return height;
|
244
|
+
height = x;
|
245
|
+
return box;
|
246
|
+
};
|
247
|
+
|
248
|
+
box.tickFormat = function(x) {
|
249
|
+
if (!arguments.length) return tickFormat;
|
250
|
+
tickFormat = x;
|
251
|
+
return box;
|
252
|
+
};
|
253
|
+
|
254
|
+
box.duration = function(x) {
|
255
|
+
if (!arguments.length) return duration;
|
256
|
+
duration = x;
|
257
|
+
return box;
|
258
|
+
};
|
259
|
+
|
260
|
+
box.domain = function(x) {
|
261
|
+
if (!arguments.length) return domain;
|
262
|
+
domain = x == null ? x : d3.functor(x);
|
263
|
+
return box;
|
264
|
+
};
|
265
|
+
|
266
|
+
box.value = function(x) {
|
267
|
+
if (!arguments.length) return value;
|
268
|
+
value = x;
|
269
|
+
return box;
|
270
|
+
};
|
271
|
+
|
272
|
+
box.whiskers = function(x) {
|
273
|
+
if (!arguments.length) return whiskers;
|
274
|
+
whiskers = x;
|
275
|
+
return box;
|
276
|
+
};
|
277
|
+
|
278
|
+
box.quartiles = function(x) {
|
279
|
+
if (!arguments.length) return quartiles;
|
280
|
+
quartiles = x;
|
281
|
+
return box;
|
282
|
+
};
|
283
|
+
|
284
|
+
return box;
|
285
|
+
};
|
286
|
+
|
287
|
+
function d3_chart_boxWhiskers(d) {
|
288
|
+
return [0, d.length - 1];
|
289
|
+
}
|
290
|
+
|
291
|
+
function d3_chart_boxQuartiles(d) {
|
292
|
+
return [
|
293
|
+
d3.quantile(d, .25),
|
294
|
+
d3.quantile(d, .5),
|
295
|
+
d3.quantile(d, .75)
|
296
|
+
];
|
297
|
+
}
|
@@ -0,0 +1,237 @@
|
|
1
|
+
// Chart design based on the recommendations of Stephen Few. Implementation
|
2
|
+
// based on the work of Clint Ivy, Jamie Love, and Jason Davies.
|
3
|
+
// http://projects.instantcognition.com/protovis/bulletchart/
|
4
|
+
d3.chart.bullet = function() {
|
5
|
+
var orient = "left", // TODO top & bottom
|
6
|
+
reverse = false,
|
7
|
+
duration = 0,
|
8
|
+
ranges = d3_chart_bulletRanges,
|
9
|
+
markers = d3_chart_bulletMarkers,
|
10
|
+
measures = d3_chart_bulletMeasures,
|
11
|
+
width = 380,
|
12
|
+
height = 30,
|
13
|
+
tickFormat = null;
|
14
|
+
|
15
|
+
// For each small multiple…
|
16
|
+
function bullet(g) {
|
17
|
+
g.each(function(d, i) {
|
18
|
+
var rangez = ranges.call(this, d, i).slice().sort(d3.descending),
|
19
|
+
markerz = markers.call(this, d, i).slice().sort(d3.descending),
|
20
|
+
measurez = measures.call(this, d, i).slice().sort(d3.descending),
|
21
|
+
g = d3.select(this);
|
22
|
+
|
23
|
+
// Compute the new x-scale.
|
24
|
+
var x1 = d3.scale.linear()
|
25
|
+
.domain([0, Math.max(rangez[0], markerz[0], measurez[0])])
|
26
|
+
.range(reverse ? [width, 0] : [0, width]);
|
27
|
+
|
28
|
+
// Retrieve the old x-scale, if this is an update.
|
29
|
+
var x0 = this.__chart__ || d3.scale.linear()
|
30
|
+
.domain([0, Infinity])
|
31
|
+
.range(x1.range());
|
32
|
+
|
33
|
+
// Stash the new scale.
|
34
|
+
this.__chart__ = x1;
|
35
|
+
|
36
|
+
// Derive width-scales from the x-scales.
|
37
|
+
var w0 = d3_chart_bulletWidth(x0),
|
38
|
+
w1 = d3_chart_bulletWidth(x1);
|
39
|
+
|
40
|
+
// Update the range rects.
|
41
|
+
var range = g.selectAll("rect.range")
|
42
|
+
.data(rangez);
|
43
|
+
|
44
|
+
range.enter().append("svg:rect")
|
45
|
+
.attr("class", function(d, i) { return "range s" + i; })
|
46
|
+
.attr("width", w0)
|
47
|
+
.attr("height", height)
|
48
|
+
.attr("x", reverse ? x0 : 0)
|
49
|
+
.transition()
|
50
|
+
.duration(duration)
|
51
|
+
.attr("width", w1)
|
52
|
+
.attr("x", reverse ? x1 : 0);
|
53
|
+
|
54
|
+
range.transition()
|
55
|
+
.duration(duration)
|
56
|
+
.attr("x", reverse ? x1 : 0)
|
57
|
+
.attr("width", w1)
|
58
|
+
.attr("height", height);
|
59
|
+
|
60
|
+
// Update the measure rects.
|
61
|
+
var measure = g.selectAll("rect.measure")
|
62
|
+
.data(measurez);
|
63
|
+
|
64
|
+
measure.enter().append("svg:rect")
|
65
|
+
.attr("class", function(d, i) { return "measure s" + i; })
|
66
|
+
.attr("width", w0)
|
67
|
+
.attr("height", height / 3)
|
68
|
+
.attr("x", reverse ? x0 : 0)
|
69
|
+
.attr("y", height / 3)
|
70
|
+
.transition()
|
71
|
+
.duration(duration)
|
72
|
+
.attr("width", w1)
|
73
|
+
.attr("x", reverse ? x1 : 0);
|
74
|
+
|
75
|
+
measure.transition()
|
76
|
+
.duration(duration)
|
77
|
+
.attr("width", w1)
|
78
|
+
.attr("height", height / 3)
|
79
|
+
.attr("x", reverse ? x1 : 0)
|
80
|
+
.attr("y", height / 3);
|
81
|
+
|
82
|
+
// Update the marker lines.
|
83
|
+
var marker = g.selectAll("line.marker")
|
84
|
+
.data(markerz);
|
85
|
+
|
86
|
+
marker.enter().append("svg:line")
|
87
|
+
.attr("class", "marker")
|
88
|
+
.attr("x1", x0)
|
89
|
+
.attr("x2", x0)
|
90
|
+
.attr("y1", height / 6)
|
91
|
+
.attr("y2", height * 5 / 6)
|
92
|
+
.transition()
|
93
|
+
.duration(duration)
|
94
|
+
.attr("x1", x1)
|
95
|
+
.attr("x2", x1);
|
96
|
+
|
97
|
+
marker.transition()
|
98
|
+
.duration(duration)
|
99
|
+
.attr("x1", x1)
|
100
|
+
.attr("x2", x1)
|
101
|
+
.attr("y1", height / 6)
|
102
|
+
.attr("y2", height * 5 / 6);
|
103
|
+
|
104
|
+
// Compute the tick format.
|
105
|
+
var format = tickFormat || x1.tickFormat(8);
|
106
|
+
|
107
|
+
// Update the tick groups.
|
108
|
+
var tick = g.selectAll("g.tick")
|
109
|
+
.data(x1.ticks(8), function(d) {
|
110
|
+
return this.textContent || format(d);
|
111
|
+
});
|
112
|
+
|
113
|
+
// Initialize the ticks with the old scale, x0.
|
114
|
+
var tickEnter = tick.enter().append("svg:g")
|
115
|
+
.attr("class", "tick")
|
116
|
+
.attr("transform", d3_chart_bulletTranslate(x0))
|
117
|
+
.style("opacity", 1e-6);
|
118
|
+
|
119
|
+
tickEnter.append("svg:line")
|
120
|
+
.attr("y1", height)
|
121
|
+
.attr("y2", height * 7 / 6);
|
122
|
+
|
123
|
+
tickEnter.append("svg:text")
|
124
|
+
.attr("text-anchor", "middle")
|
125
|
+
.attr("dy", "1em")
|
126
|
+
.attr("y", height * 7 / 6)
|
127
|
+
.text(format);
|
128
|
+
|
129
|
+
// Transition the entering ticks to the new scale, x1.
|
130
|
+
tickEnter.transition()
|
131
|
+
.duration(duration)
|
132
|
+
.attr("transform", d3_chart_bulletTranslate(x1))
|
133
|
+
.style("opacity", 1);
|
134
|
+
|
135
|
+
// Transition the updating ticks to the new scale, x1.
|
136
|
+
var tickUpdate = tick.transition()
|
137
|
+
.duration(duration)
|
138
|
+
.attr("transform", d3_chart_bulletTranslate(x1))
|
139
|
+
.style("opacity", 1);
|
140
|
+
|
141
|
+
tickUpdate.select("line")
|
142
|
+
.attr("y1", height)
|
143
|
+
.attr("y2", height * 7 / 6);
|
144
|
+
|
145
|
+
tickUpdate.select("text")
|
146
|
+
.attr("y", height * 7 / 6);
|
147
|
+
|
148
|
+
// Transition the exiting ticks to the new scale, x1.
|
149
|
+
tick.exit().transition()
|
150
|
+
.duration(duration)
|
151
|
+
.attr("transform", d3_chart_bulletTranslate(x1))
|
152
|
+
.style("opacity", 1e-6)
|
153
|
+
.remove();
|
154
|
+
});
|
155
|
+
d3.timer.flush();
|
156
|
+
}
|
157
|
+
|
158
|
+
// left, right, top, bottom
|
159
|
+
bullet.orient = function(x) {
|
160
|
+
if (!arguments.length) return orient;
|
161
|
+
orient = x;
|
162
|
+
reverse = orient == "right" || orient == "bottom";
|
163
|
+
return bullet;
|
164
|
+
};
|
165
|
+
|
166
|
+
// ranges (bad, satisfactory, good)
|
167
|
+
bullet.ranges = function(x) {
|
168
|
+
if (!arguments.length) return ranges;
|
169
|
+
ranges = x;
|
170
|
+
return bullet;
|
171
|
+
};
|
172
|
+
|
173
|
+
// markers (previous, goal)
|
174
|
+
bullet.markers = function(x) {
|
175
|
+
if (!arguments.length) return markers;
|
176
|
+
markers = x;
|
177
|
+
return bullet;
|
178
|
+
};
|
179
|
+
|
180
|
+
// measures (actual, forecast)
|
181
|
+
bullet.measures = function(x) {
|
182
|
+
if (!arguments.length) return measures;
|
183
|
+
measures = x;
|
184
|
+
return bullet;
|
185
|
+
};
|
186
|
+
|
187
|
+
bullet.width = function(x) {
|
188
|
+
if (!arguments.length) return width;
|
189
|
+
width = x;
|
190
|
+
return bullet;
|
191
|
+
};
|
192
|
+
|
193
|
+
bullet.height = function(x) {
|
194
|
+
if (!arguments.length) return height;
|
195
|
+
height = x;
|
196
|
+
return bullet;
|
197
|
+
};
|
198
|
+
|
199
|
+
bullet.tickFormat = function(x) {
|
200
|
+
if (!arguments.length) return tickFormat;
|
201
|
+
tickFormat = x;
|
202
|
+
return bullet;
|
203
|
+
};
|
204
|
+
|
205
|
+
bullet.duration = function(x) {
|
206
|
+
if (!arguments.length) return duration;
|
207
|
+
duration = x;
|
208
|
+
return bullet;
|
209
|
+
};
|
210
|
+
|
211
|
+
return bullet;
|
212
|
+
};
|
213
|
+
|
214
|
+
function d3_chart_bulletRanges(d) {
|
215
|
+
return d.ranges;
|
216
|
+
}
|
217
|
+
|
218
|
+
function d3_chart_bulletMarkers(d) {
|
219
|
+
return d.markers;
|
220
|
+
}
|
221
|
+
|
222
|
+
function d3_chart_bulletMeasures(d) {
|
223
|
+
return d.measures;
|
224
|
+
}
|
225
|
+
|
226
|
+
function d3_chart_bulletTranslate(x) {
|
227
|
+
return function(d) {
|
228
|
+
return "translate(" + x(d) + ",0)";
|
229
|
+
};
|
230
|
+
}
|
231
|
+
|
232
|
+
function d3_chart_bulletWidth(x) {
|
233
|
+
var x0 = x(0);
|
234
|
+
return function(d) {
|
235
|
+
return Math.abs(x(d) - x0);
|
236
|
+
};
|
237
|
+
}
|