|
1 (function(){if (!Date.now) Date.now = function() { |
|
2 return +new Date; |
|
3 }; |
|
4 try { |
|
5 document.createElement("div").style.setProperty("opacity", 0, ""); |
|
6 } catch (error) { |
|
7 var d3_style_prototype = CSSStyleDeclaration.prototype, |
|
8 d3_style_setProperty = d3_style_prototype.setProperty; |
|
9 d3_style_prototype.setProperty = function(name, value, priority) { |
|
10 d3_style_setProperty.call(this, name, value + "", priority); |
|
11 }; |
|
12 } |
|
13 d3 = {version: "2.5.0"}; // semver |
|
14 var d3_array = d3_arraySlice; // conversion for NodeLists |
|
15 |
|
16 function d3_arrayCopy(pseudoarray) { |
|
17 var i = -1, n = pseudoarray.length, array = []; |
|
18 while (++i < n) array.push(pseudoarray[i]); |
|
19 return array; |
|
20 } |
|
21 |
|
22 function d3_arraySlice(pseudoarray) { |
|
23 return Array.prototype.slice.call(pseudoarray); |
|
24 } |
|
25 |
|
26 try { |
|
27 d3_array(document.documentElement.childNodes)[0].nodeType; |
|
28 } catch(e) { |
|
29 d3_array = d3_arrayCopy; |
|
30 } |
|
31 |
|
32 var d3_arraySubclass = [].__proto__? |
|
33 |
|
34 // Until ECMAScript supports array subclassing, prototype injection works well. |
|
35 function(array, prototype) { |
|
36 array.__proto__ = prototype; |
|
37 }: |
|
38 |
|
39 // And if your browser doesn't support __proto__, we'll use direct extension. |
|
40 function(array, prototype) { |
|
41 for (var property in prototype) array[property] = prototype[property]; |
|
42 }; |
|
43 function d3_this() { |
|
44 return this; |
|
45 } |
|
46 d3.functor = function(v) { |
|
47 return typeof v === "function" ? v : function() { return v; }; |
|
48 }; |
|
49 // A getter-setter method that preserves the appropriate `this` context. |
|
50 d3.rebind = function(object, method) { |
|
51 return function() { |
|
52 var x = method.apply(object, arguments); |
|
53 return arguments.length ? object : x; |
|
54 }; |
|
55 }; |
|
56 d3.ascending = function(a, b) { |
|
57 return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; |
|
58 }; |
|
59 d3.descending = function(a, b) { |
|
60 return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; |
|
61 }; |
|
62 d3.mean = function(array, f) { |
|
63 var n = array.length, |
|
64 a, |
|
65 m = 0, |
|
66 i = -1, |
|
67 j = 0; |
|
68 if (arguments.length === 1) { |
|
69 while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j; |
|
70 } else { |
|
71 while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j; |
|
72 } |
|
73 return j ? m : undefined; |
|
74 }; |
|
75 d3.median = function(array, f) { |
|
76 if (arguments.length > 1) array = array.map(f); |
|
77 array = array.filter(d3_number); |
|
78 return array.length ? d3.quantile(array.sort(d3.ascending), .5) : undefined; |
|
79 }; |
|
80 d3.min = function(array, f) { |
|
81 var i = -1, |
|
82 n = array.length, |
|
83 a, |
|
84 b; |
|
85 if (arguments.length === 1) { |
|
86 while (++i < n && ((a = array[i]) == null || a != a)) a = undefined; |
|
87 while (++i < n) if ((b = array[i]) != null && a > b) a = b; |
|
88 } else { |
|
89 while (++i < n && ((a = f.call(array, array[i], i)) == null || a != a)) a = undefined; |
|
90 while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b; |
|
91 } |
|
92 return a; |
|
93 }; |
|
94 d3.max = function(array, f) { |
|
95 var i = -1, |
|
96 n = array.length, |
|
97 a, |
|
98 b; |
|
99 if (arguments.length === 1) { |
|
100 while (++i < n && ((a = array[i]) == null || a != a)) a = undefined; |
|
101 while (++i < n) if ((b = array[i]) != null && b > a) a = b; |
|
102 } else { |
|
103 while (++i < n && ((a = f.call(array, array[i], i)) == null || a != a)) a = undefined; |
|
104 while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b; |
|
105 } |
|
106 return a; |
|
107 }; |
|
108 d3.extent = function(array, f) { |
|
109 var i = -1, |
|
110 n = array.length, |
|
111 a, |
|
112 b, |
|
113 c; |
|
114 if (arguments.length === 1) { |
|
115 while (++i < n && ((a = c = array[i]) == null || a != a)) a = c = undefined; |
|
116 while (++i < n) if ((b = array[i]) != null) { |
|
117 if (a > b) a = b; |
|
118 if (c < b) c = b; |
|
119 } |
|
120 } else { |
|
121 while (++i < n && ((a = c = f.call(array, array[i], i)) == null || a != a)) a = undefined; |
|
122 while (++i < n) if ((b = f.call(array, array[i], i)) != null) { |
|
123 if (a > b) a = b; |
|
124 if (c < b) c = b; |
|
125 } |
|
126 } |
|
127 return [a, c]; |
|
128 }; |
|
129 d3.random = { |
|
130 normal: function(mean, deviation) { |
|
131 if (arguments.length < 2) deviation = 1; |
|
132 if (arguments.length < 1) mean = 0; |
|
133 return function() { |
|
134 var x, y, r; |
|
135 do { |
|
136 x = Math.random() * 2 - 1; |
|
137 y = Math.random() * 2 - 1; |
|
138 r = x * x + y * y; |
|
139 } while (!r || r > 1); |
|
140 return mean + deviation * x * Math.sqrt(-2 * Math.log(r) / r); |
|
141 }; |
|
142 } |
|
143 }; |
|
144 function d3_number(x) { |
|
145 return x != null && !isNaN(x); |
|
146 } |
|
147 d3.sum = function(array, f) { |
|
148 var s = 0, |
|
149 n = array.length, |
|
150 a, |
|
151 i = -1; |
|
152 |
|
153 if (arguments.length === 1) { |
|
154 while (++i < n) if (!isNaN(a = +array[i])) s += a; |
|
155 } else { |
|
156 while (++i < n) if (!isNaN(a = +f.call(array, array[i], i))) s += a; |
|
157 } |
|
158 |
|
159 return s; |
|
160 }; |
|
161 // R-7 per <http://en.wikipedia.org/wiki/Quantile> |
|
162 d3.quantile = function(values, p) { |
|
163 var H = (values.length - 1) * p + 1, |
|
164 h = Math.floor(H), |
|
165 v = values[h - 1], |
|
166 e = H - h; |
|
167 return e ? v + e * (values[h] - v) : v; |
|
168 }; |
|
169 d3.zip = function() { |
|
170 if (!(n = arguments.length)) return []; |
|
171 for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m;) { |
|
172 for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n;) { |
|
173 zip[j] = arguments[j][i]; |
|
174 } |
|
175 } |
|
176 return zips; |
|
177 }; |
|
178 |
|
179 function d3_zipLength(d) { |
|
180 return d.length; |
|
181 } |
|
182 // Locate the insertion point for x in a to maintain sorted order. The |
|
183 // arguments lo and hi may be used to specify a subset of the array which should |
|
184 // be considered; by default the entire array is used. If x is already present |
|
185 // in a, the insertion point will be before (to the left of) any existing |
|
186 // entries. The return value is suitable for use as the first argument to |
|
187 // `array.splice` assuming that a is already sorted. |
|
188 // |
|
189 // The returned insertion point i partitions the array a into two halves so that |
|
190 // all v < x for v in a[lo:i] for the left side and all v >= x for v in a[i:hi] |
|
191 // for the right side. |
|
192 d3.bisectLeft = function(a, x, lo, hi) { |
|
193 if (arguments.length < 3) lo = 0; |
|
194 if (arguments.length < 4) hi = a.length; |
|
195 while (lo < hi) { |
|
196 var mid = (lo + hi) >> 1; |
|
197 if (a[mid] < x) lo = mid + 1; |
|
198 else hi = mid; |
|
199 } |
|
200 return lo; |
|
201 }; |
|
202 |
|
203 // Similar to bisectLeft, but returns an insertion point which comes after (to |
|
204 // the right of) any existing entries of x in a. |
|
205 // |
|
206 // The returned insertion point i partitions the array into two halves so that |
|
207 // all v <= x for v in a[lo:i] for the left side and all v > x for v in a[i:hi] |
|
208 // for the right side. |
|
209 d3.bisect = |
|
210 d3.bisectRight = function(a, x, lo, hi) { |
|
211 if (arguments.length < 3) lo = 0; |
|
212 if (arguments.length < 4) hi = a.length; |
|
213 while (lo < hi) { |
|
214 var mid = (lo + hi) >> 1; |
|
215 if (x < a[mid]) hi = mid; |
|
216 else lo = mid + 1; |
|
217 } |
|
218 return lo; |
|
219 }; |
|
220 d3.first = function(array, f) { |
|
221 var i = 0, |
|
222 n = array.length, |
|
223 a = array[0], |
|
224 b; |
|
225 if (arguments.length === 1) f = d3.ascending; |
|
226 while (++i < n) { |
|
227 if (f.call(array, a, b = array[i]) > 0) { |
|
228 a = b; |
|
229 } |
|
230 } |
|
231 return a; |
|
232 }; |
|
233 d3.last = function(array, f) { |
|
234 var i = 0, |
|
235 n = array.length, |
|
236 a = array[0], |
|
237 b; |
|
238 if (arguments.length === 1) f = d3.ascending; |
|
239 while (++i < n) { |
|
240 if (f.call(array, a, b = array[i]) <= 0) { |
|
241 a = b; |
|
242 } |
|
243 } |
|
244 return a; |
|
245 }; |
|
246 d3.nest = function() { |
|
247 var nest = {}, |
|
248 keys = [], |
|
249 sortKeys = [], |
|
250 sortValues, |
|
251 rollup; |
|
252 |
|
253 function map(array, depth) { |
|
254 if (depth >= keys.length) return rollup |
|
255 ? rollup.call(nest, array) : (sortValues |
|
256 ? array.sort(sortValues) |
|
257 : array); |
|
258 |
|
259 var i = -1, |
|
260 n = array.length, |
|
261 key = keys[depth++], |
|
262 keyValue, |
|
263 object, |
|
264 o = {}; |
|
265 |
|
266 while (++i < n) { |
|
267 if ((keyValue = key(object = array[i])) in o) { |
|
268 o[keyValue].push(object); |
|
269 } else { |
|
270 o[keyValue] = [object]; |
|
271 } |
|
272 } |
|
273 |
|
274 for (keyValue in o) { |
|
275 o[keyValue] = map(o[keyValue], depth); |
|
276 } |
|
277 |
|
278 return o; |
|
279 } |
|
280 |
|
281 function entries(map, depth) { |
|
282 if (depth >= keys.length) return map; |
|
283 |
|
284 var a = [], |
|
285 sortKey = sortKeys[depth++], |
|
286 key; |
|
287 |
|
288 for (key in map) { |
|
289 a.push({key: key, values: entries(map[key], depth)}); |
|
290 } |
|
291 |
|
292 if (sortKey) a.sort(function(a, b) { |
|
293 return sortKey(a.key, b.key); |
|
294 }); |
|
295 |
|
296 return a; |
|
297 } |
|
298 |
|
299 nest.map = function(array) { |
|
300 return map(array, 0); |
|
301 }; |
|
302 |
|
303 nest.entries = function(array) { |
|
304 return entries(map(array, 0), 0); |
|
305 }; |
|
306 |
|
307 nest.key = function(d) { |
|
308 keys.push(d); |
|
309 return nest; |
|
310 }; |
|
311 |
|
312 // Specifies the order for the most-recently specified key. |
|
313 // Note: only applies to entries. Map keys are unordered! |
|
314 nest.sortKeys = function(order) { |
|
315 sortKeys[keys.length - 1] = order; |
|
316 return nest; |
|
317 }; |
|
318 |
|
319 // Specifies the order for leaf values. |
|
320 // Applies to both maps and entries array. |
|
321 nest.sortValues = function(order) { |
|
322 sortValues = order; |
|
323 return nest; |
|
324 }; |
|
325 |
|
326 nest.rollup = function(f) { |
|
327 rollup = f; |
|
328 return nest; |
|
329 }; |
|
330 |
|
331 return nest; |
|
332 }; |
|
333 d3.keys = function(map) { |
|
334 var keys = []; |
|
335 for (var key in map) keys.push(key); |
|
336 return keys; |
|
337 }; |
|
338 d3.values = function(map) { |
|
339 var values = []; |
|
340 for (var key in map) values.push(map[key]); |
|
341 return values; |
|
342 }; |
|
343 d3.entries = function(map) { |
|
344 var entries = []; |
|
345 for (var key in map) entries.push({key: key, value: map[key]}); |
|
346 return entries; |
|
347 }; |
|
348 d3.permute = function(array, indexes) { |
|
349 var permutes = [], |
|
350 i = -1, |
|
351 n = indexes.length; |
|
352 while (++i < n) permutes[i] = array[indexes[i]]; |
|
353 return permutes; |
|
354 }; |
|
355 d3.merge = function(arrays) { |
|
356 return Array.prototype.concat.apply([], arrays); |
|
357 }; |
|
358 d3.split = function(array, f) { |
|
359 var arrays = [], |
|
360 values = [], |
|
361 value, |
|
362 i = -1, |
|
363 n = array.length; |
|
364 if (arguments.length < 2) f = d3_splitter; |
|
365 while (++i < n) { |
|
366 if (f.call(values, value = array[i], i)) { |
|
367 values = []; |
|
368 } else { |
|
369 if (!values.length) arrays.push(values); |
|
370 values.push(value); |
|
371 } |
|
372 } |
|
373 return arrays; |
|
374 }; |
|
375 |
|
376 function d3_splitter(d) { |
|
377 return d == null; |
|
378 } |
|
379 function d3_collapse(s) { |
|
380 return s.replace(/(^\s+)|(\s+$)/g, "").replace(/\s+/g, " "); |
|
381 } |
|
382 /** |
|
383 * @param {number} |
|
384 * start |
|
385 * @param {number=} |
|
386 * stop |
|
387 * @param {number=} |
|
388 * step |
|
389 */ |
|
390 d3.range = function(start, stop, step) { |
|
391 if (arguments.length < 3) { |
|
392 step = 1; |
|
393 if (arguments.length < 2) { |
|
394 stop = start; |
|
395 start = 0; |
|
396 } |
|
397 } |
|
398 if ((stop - start) / step == Infinity) throw new Error("infinite range"); |
|
399 var range = [], |
|
400 i = -1, |
|
401 j; |
|
402 if (step < 0) while ((j = start + step * ++i) > stop) range.push(j); |
|
403 else while ((j = start + step * ++i) < stop) range.push(j); |
|
404 return range; |
|
405 }; |
|
406 d3.requote = function(s) { |
|
407 return s.replace(d3_requote_re, "\\$&"); |
|
408 }; |
|
409 |
|
410 var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; |
|
411 d3.round = function(x, n) { |
|
412 return n |
|
413 ? Math.round(x * Math.pow(10, n)) * Math.pow(10, -n) |
|
414 : Math.round(x); |
|
415 }; |
|
416 d3.xhr = function(url, mime, callback) { |
|
417 var req = new XMLHttpRequest; |
|
418 if (arguments.length < 3) callback = mime; |
|
419 else if (mime && req.overrideMimeType) req.overrideMimeType(mime); |
|
420 req.open("GET", url, true); |
|
421 req.onreadystatechange = function() { |
|
422 if (req.readyState === 4) callback(req.status < 300 ? req : null); |
|
423 }; |
|
424 req.send(null); |
|
425 }; |
|
426 d3.text = function(url, mime, callback) { |
|
427 function ready(req) { |
|
428 callback(req && req.responseText); |
|
429 } |
|
430 if (arguments.length < 3) { |
|
431 callback = mime; |
|
432 mime = null; |
|
433 } |
|
434 d3.xhr(url, mime, ready); |
|
435 }; |
|
436 d3.json = function(url, callback) { |
|
437 d3.text(url, "application/json", function(text) { |
|
438 callback(text ? JSON.parse(text) : null); |
|
439 }); |
|
440 }; |
|
441 d3.html = function(url, callback) { |
|
442 d3.text(url, "text/html", function(text) { |
|
443 if (text != null) { // Treat empty string as valid HTML. |
|
444 var range = document.createRange(); |
|
445 range.selectNode(document.body); |
|
446 text = range.createContextualFragment(text); |
|
447 } |
|
448 callback(text); |
|
449 }); |
|
450 }; |
|
451 d3.xml = function(url, mime, callback) { |
|
452 function ready(req) { |
|
453 callback(req && req.responseXML); |
|
454 } |
|
455 if (arguments.length < 3) { |
|
456 callback = mime; |
|
457 mime = null; |
|
458 } |
|
459 d3.xhr(url, mime, ready); |
|
460 }; |
|
461 d3.ns = { |
|
462 |
|
463 prefix: { |
|
464 svg: "http://www.w3.org/2000/svg", |
|
465 xhtml: "http://www.w3.org/1999/xhtml", |
|
466 xlink: "http://www.w3.org/1999/xlink", |
|
467 xml: "http://www.w3.org/XML/1998/namespace", |
|
468 xmlns: "http://www.w3.org/2000/xmlns/" |
|
469 }, |
|
470 |
|
471 qualify: function(name) { |
|
472 var i = name.indexOf(":"); |
|
473 return i < 0 ? name : { |
|
474 space: d3.ns.prefix[name.substring(0, i)], |
|
475 local: name.substring(i + 1) |
|
476 }; |
|
477 } |
|
478 |
|
479 }; |
|
480 d3.dispatch = function() { |
|
481 var dispatch = new d3_dispatch(), |
|
482 i = -1, |
|
483 n = arguments.length; |
|
484 while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(); |
|
485 return dispatch; |
|
486 }; |
|
487 |
|
488 function d3_dispatch() {} |
|
489 |
|
490 d3_dispatch.prototype.on = function(type, listener) { |
|
491 var i = type.indexOf("."), |
|
492 name = ""; |
|
493 |
|
494 // Extract optional namespace, e.g., "click.foo" |
|
495 if (i > 0) { |
|
496 name = type.substring(i + 1); |
|
497 type = type.substring(0, i); |
|
498 } |
|
499 |
|
500 this[type].on(name, listener); |
|
501 }; |
|
502 |
|
503 function d3_dispatch_event() { |
|
504 var listeners = [], |
|
505 listenerByName = {}; |
|
506 |
|
507 function dispatch() { |
|
508 var z = listeners, // defensive reference |
|
509 i = -1, |
|
510 n = z.length, |
|
511 l; |
|
512 while (++i < n) if ((l = z[i])._on) l.apply(this, arguments); |
|
513 } |
|
514 |
|
515 dispatch.on = function(name, listener) { |
|
516 var l, i; |
|
517 |
|
518 // remove the old listener, if any |
|
519 if (l = listenerByName[name]) { |
|
520 l._on = false; |
|
521 listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1)); |
|
522 delete listenerByName[name]; |
|
523 } |
|
524 |
|
525 // add the new listener, if any |
|
526 if (listener) { |
|
527 listener._on = true; |
|
528 listeners.push(listener); |
|
529 listenerByName[name] = listener; |
|
530 } |
|
531 |
|
532 return dispatch; |
|
533 }; |
|
534 |
|
535 return dispatch; |
|
536 }; |
|
537 // TODO align |
|
538 d3.format = function(specifier) { |
|
539 var match = d3_format_re.exec(specifier), |
|
540 fill = match[1] || " ", |
|
541 sign = match[3] || "", |
|
542 zfill = match[5], |
|
543 width = +match[6], |
|
544 comma = match[7], |
|
545 precision = match[8], |
|
546 type = match[9], |
|
547 scale = 1, |
|
548 suffix = "", |
|
549 integer = false; |
|
550 |
|
551 if (precision) precision = +precision.substring(1); |
|
552 |
|
553 if (zfill) { |
|
554 fill = "0"; // TODO align = "="; |
|
555 if (comma) width -= Math.floor((width - 1) / 4); |
|
556 } |
|
557 |
|
558 switch (type) { |
|
559 case "n": comma = true; type = "g"; break; |
|
560 case "%": scale = 100; suffix = "%"; type = "f"; break; |
|
561 case "p": scale = 100; suffix = "%"; type = "r"; break; |
|
562 case "d": integer = true; precision = 0; break; |
|
563 case "s": scale = -1; type = "r"; break; |
|
564 } |
|
565 |
|
566 // If no precision is specified for r, fallback to general notation. |
|
567 if (type == "r" && !precision) type = "g"; |
|
568 |
|
569 type = d3_format_types[type] || d3_format_typeDefault; |
|
570 |
|
571 return function(value) { |
|
572 |
|
573 // Return the empty string for floats formatted as ints. |
|
574 if (integer && (value % 1)) return ""; |
|
575 |
|
576 // Convert negative to positive, and record the sign prefix. |
|
577 var negative = (value < 0) && (value = -value) ? "\u2212" : sign; |
|
578 |
|
579 // Apply the scale, computing it from the value's exponent for si format. |
|
580 if (scale < 0) { |
|
581 var prefix = d3.formatPrefix(value, precision); |
|
582 value *= prefix.scale; |
|
583 suffix = prefix.symbol; |
|
584 } else { |
|
585 value *= scale; |
|
586 } |
|
587 |
|
588 // Convert to the desired precision. |
|
589 value = type(value, precision); |
|
590 |
|
591 // If the fill character is 0, the sign and group is applied after the fill. |
|
592 if (zfill) { |
|
593 var length = value.length + negative.length; |
|
594 if (length < width) value = new Array(width - length + 1).join(fill) + value; |
|
595 if (comma) value = d3_format_group(value); |
|
596 value = negative + value; |
|
597 } |
|
598 |
|
599 // Otherwise (e.g., space-filling), the sign and group is applied before. |
|
600 else { |
|
601 if (comma) value = d3_format_group(value); |
|
602 value = negative + value; |
|
603 var length = value.length; |
|
604 if (length < width) value = new Array(width - length + 1).join(fill) + value; |
|
605 } |
|
606 |
|
607 return value + suffix; |
|
608 }; |
|
609 }; |
|
610 |
|
611 // [[fill]align][sign][#][0][width][,][.precision][type] |
|
612 var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/; |
|
613 |
|
614 var d3_format_types = { |
|
615 g: function(x, p) { return x.toPrecision(p); }, |
|
616 e: function(x, p) { return x.toExponential(p); }, |
|
617 f: function(x, p) { return x.toFixed(p); }, |
|
618 r: function(x, p) { return d3.round(x, p = d3_format_precision(x, p)).toFixed(Math.max(0, Math.min(20, p))); } |
|
619 }; |
|
620 |
|
621 function d3_format_precision(x, p) { |
|
622 return p - (x ? 1 + Math.floor(Math.log(x + Math.pow(10, 1 + Math.floor(Math.log(x) / Math.LN10) - p)) / Math.LN10) : 1); |
|
623 } |
|
624 |
|
625 function d3_format_typeDefault(x) { |
|
626 return x + ""; |
|
627 } |
|
628 |
|
629 // Apply comma grouping for thousands. |
|
630 function d3_format_group(value) { |
|
631 var i = value.lastIndexOf("."), |
|
632 f = i >= 0 ? value.substring(i) : (i = value.length, ""), |
|
633 t = []; |
|
634 while (i > 0) t.push(value.substring(i -= 3, i + 3)); |
|
635 return t.reverse().join(",") + f; |
|
636 } |
|
637 var d3_formatPrefixes = ["y","z","a","f","p","n","μ","m","","k","M","G","T","P","E","Z","Y"].map(d3_formatPrefix); |
|
638 |
|
639 d3.formatPrefix = function(value, precision) { |
|
640 var i = 0; |
|
641 if (value) { |
|
642 if (value < 0) value *= -1; |
|
643 if (precision) value = d3.round(value, d3_format_precision(value, precision)); |
|
644 i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); |
|
645 i = Math.max(-24, Math.min(24, Math.floor((i <= 0 ? i + 1 : i - 1) / 3) * 3)); |
|
646 } |
|
647 return d3_formatPrefixes[8 + i / 3]; |
|
648 }; |
|
649 |
|
650 function d3_formatPrefix(d, i) { |
|
651 return { |
|
652 scale: Math.pow(10, (8 - i) * 3), |
|
653 symbol: d |
|
654 }; |
|
655 } |
|
656 |
|
657 /* |
|
658 * TERMS OF USE - EASING EQUATIONS |
|
659 * |
|
660 * Open source under the BSD License. |
|
661 * |
|
662 * Copyright 2001 Robert Penner All rights reserved. |
|
663 * |
|
664 * Redistribution and use in source and binary forms, with or without |
|
665 * modification, are permitted provided that the following conditions are met: |
|
666 * - Redistributions of source code must retain the above copyright notice, |
|
667 * this list of conditions and the following disclaimer. |
|
668 * - Redistributions in binary form must reproduce the above copyright notice, |
|
669 * this list of conditions and the following disclaimer in the documentation |
|
670 * and/or other materials provided with the distribution. |
|
671 * - Neither the name of the author nor the names of contributors may be used |
|
672 * to endorse or promote products derived from this software without specific |
|
673 * prior written permission. |
|
674 * |
|
675 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
676 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
677 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
678 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
|
679 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
680 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
681 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
682 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
683 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
684 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
685 * POSSIBILITY OF SUCH DAMAGE. |
|
686 */ |
|
687 |
|
688 var d3_ease_quad = d3_ease_poly(2), |
|
689 d3_ease_cubic = d3_ease_poly(3); |
|
690 |
|
691 var d3_ease = { |
|
692 linear: function() { return d3_ease_linear; }, |
|
693 poly: d3_ease_poly, |
|
694 quad: function() { return d3_ease_quad; }, |
|
695 cubic: function() { return d3_ease_cubic; }, |
|
696 sin: function() { return d3_ease_sin; }, |
|
697 exp: function() { return d3_ease_exp; }, |
|
698 circle: function() { return d3_ease_circle; }, |
|
699 elastic: d3_ease_elastic, |
|
700 back: d3_ease_back, |
|
701 bounce: function() { return d3_ease_bounce; } |
|
702 }; |
|
703 |
|
704 var d3_ease_mode = { |
|
705 "in": function(f) { return f; }, |
|
706 "out": d3_ease_reverse, |
|
707 "in-out": d3_ease_reflect, |
|
708 "out-in": function(f) { return d3_ease_reflect(d3_ease_reverse(f)); } |
|
709 }; |
|
710 |
|
711 d3.ease = function(name) { |
|
712 var i = name.indexOf("-"), |
|
713 t = i >= 0 ? name.substring(0, i) : name, |
|
714 m = i >= 0 ? name.substring(i + 1) : "in"; |
|
715 return d3_ease_clamp(d3_ease_mode[m](d3_ease[t].apply(null, Array.prototype.slice.call(arguments, 1)))); |
|
716 }; |
|
717 |
|
718 function d3_ease_clamp(f) { |
|
719 return function(t) { |
|
720 return t <= 0 ? 0 : t >= 1 ? 1 : f(t); |
|
721 }; |
|
722 } |
|
723 |
|
724 function d3_ease_reverse(f) { |
|
725 return function(t) { |
|
726 return 1 - f(1 - t); |
|
727 }; |
|
728 } |
|
729 |
|
730 function d3_ease_reflect(f) { |
|
731 return function(t) { |
|
732 return .5 * (t < .5 ? f(2 * t) : (2 - f(2 - 2 * t))); |
|
733 }; |
|
734 } |
|
735 |
|
736 function d3_ease_linear(t) { |
|
737 return t; |
|
738 } |
|
739 |
|
740 function d3_ease_poly(e) { |
|
741 return function(t) { |
|
742 return Math.pow(t, e); |
|
743 } |
|
744 } |
|
745 |
|
746 function d3_ease_sin(t) { |
|
747 return 1 - Math.cos(t * Math.PI / 2); |
|
748 } |
|
749 |
|
750 function d3_ease_exp(t) { |
|
751 return Math.pow(2, 10 * (t - 1)); |
|
752 } |
|
753 |
|
754 function d3_ease_circle(t) { |
|
755 return 1 - Math.sqrt(1 - t * t); |
|
756 } |
|
757 |
|
758 function d3_ease_elastic(a, p) { |
|
759 var s; |
|
760 if (arguments.length < 2) p = 0.45; |
|
761 if (arguments.length < 1) { a = 1; s = p / 4; } |
|
762 else s = p / (2 * Math.PI) * Math.asin(1 / a); |
|
763 return function(t) { |
|
764 return 1 + a * Math.pow(2, 10 * -t) * Math.sin((t - s) * 2 * Math.PI / p); |
|
765 }; |
|
766 } |
|
767 |
|
768 function d3_ease_back(s) { |
|
769 if (!s) s = 1.70158; |
|
770 return function(t) { |
|
771 return t * t * ((s + 1) * t - s); |
|
772 }; |
|
773 } |
|
774 |
|
775 function d3_ease_bounce(t) { |
|
776 return t < 1 / 2.75 ? 7.5625 * t * t |
|
777 : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 |
|
778 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 |
|
779 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375; |
|
780 } |
|
781 d3.event = null; |
|
782 |
|
783 function d3_eventCancel() { |
|
784 d3.event.stopPropagation(); |
|
785 d3.event.preventDefault(); |
|
786 } |
|
787 d3.interpolate = function(a, b) { |
|
788 var i = d3.interpolators.length, f; |
|
789 while (--i >= 0 && !(f = d3.interpolators[i](a, b))); |
|
790 return f; |
|
791 }; |
|
792 |
|
793 d3.interpolateNumber = function(a, b) { |
|
794 b -= a; |
|
795 return function(t) { return a + b * t; }; |
|
796 }; |
|
797 |
|
798 d3.interpolateRound = function(a, b) { |
|
799 b -= a; |
|
800 return function(t) { return Math.round(a + b * t); }; |
|
801 }; |
|
802 |
|
803 d3.interpolateString = function(a, b) { |
|
804 var m, // current match |
|
805 i, // current index |
|
806 j, // current index (for coallescing) |
|
807 s0 = 0, // start index of current string prefix |
|
808 s1 = 0, // end index of current string prefix |
|
809 s = [], // string constants and placeholders |
|
810 q = [], // number interpolators |
|
811 n, // q.length |
|
812 o; |
|
813 |
|
814 // Reset our regular expression! |
|
815 d3_interpolate_number.lastIndex = 0; |
|
816 |
|
817 // Find all numbers in b. |
|
818 for (i = 0; m = d3_interpolate_number.exec(b); ++i) { |
|
819 if (m.index) s.push(b.substring(s0, s1 = m.index)); |
|
820 q.push({i: s.length, x: m[0]}); |
|
821 s.push(null); |
|
822 s0 = d3_interpolate_number.lastIndex; |
|
823 } |
|
824 if (s0 < b.length) s.push(b.substring(s0)); |
|
825 |
|
826 // Find all numbers in a. |
|
827 for (i = 0, n = q.length; (m = d3_interpolate_number.exec(a)) && i < n; ++i) { |
|
828 o = q[i]; |
|
829 if (o.x == m[0]) { // The numbers match, so coallesce. |
|
830 if (o.i) { |
|
831 if (s[o.i + 1] == null) { // This match is followed by another number. |
|
832 s[o.i - 1] += o.x; |
|
833 s.splice(o.i, 1); |
|
834 for (j = i + 1; j < n; ++j) q[j].i--; |
|
835 } else { // This match is followed by a string, so coallesce twice. |
|
836 s[o.i - 1] += o.x + s[o.i + 1]; |
|
837 s.splice(o.i, 2); |
|
838 for (j = i + 1; j < n; ++j) q[j].i -= 2; |
|
839 } |
|
840 } else { |
|
841 if (s[o.i + 1] == null) { // This match is followed by another number. |
|
842 s[o.i] = o.x; |
|
843 } else { // This match is followed by a string, so coallesce twice. |
|
844 s[o.i] = o.x + s[o.i + 1]; |
|
845 s.splice(o.i + 1, 1); |
|
846 for (j = i + 1; j < n; ++j) q[j].i--; |
|
847 } |
|
848 } |
|
849 q.splice(i, 1); |
|
850 n--; |
|
851 i--; |
|
852 } else { |
|
853 o.x = d3.interpolateNumber(parseFloat(m[0]), parseFloat(o.x)); |
|
854 } |
|
855 } |
|
856 |
|
857 // Remove any numbers in b not found in a. |
|
858 while (i < n) { |
|
859 o = q.pop(); |
|
860 if (s[o.i + 1] == null) { // This match is followed by another number. |
|
861 s[o.i] = o.x; |
|
862 } else { // This match is followed by a string, so coallesce twice. |
|
863 s[o.i] = o.x + s[o.i + 1]; |
|
864 s.splice(o.i + 1, 1); |
|
865 } |
|
866 n--; |
|
867 } |
|
868 |
|
869 // Special optimization for only a single match. |
|
870 if (s.length === 1) { |
|
871 return s[0] == null ? q[0].x : function() { return b; }; |
|
872 } |
|
873 |
|
874 // Otherwise, interpolate each of the numbers and rejoin the string. |
|
875 return function(t) { |
|
876 for (i = 0; i < n; ++i) s[(o = q[i]).i] = o.x(t); |
|
877 return s.join(""); |
|
878 }; |
|
879 }; |
|
880 |
|
881 d3.interpolateTransform = function(a, b) { |
|
882 return d3.interpolateString(d3.transform(a) + "", d3.transform(b) + ""); |
|
883 }; |
|
884 |
|
885 d3.interpolateRgb = function(a, b) { |
|
886 a = d3.rgb(a); |
|
887 b = d3.rgb(b); |
|
888 var ar = a.r, |
|
889 ag = a.g, |
|
890 ab = a.b, |
|
891 br = b.r - ar, |
|
892 bg = b.g - ag, |
|
893 bb = b.b - ab; |
|
894 return function(t) { |
|
895 return "#" |
|
896 + d3_rgb_hex(Math.round(ar + br * t)) |
|
897 + d3_rgb_hex(Math.round(ag + bg * t)) |
|
898 + d3_rgb_hex(Math.round(ab + bb * t)); |
|
899 }; |
|
900 }; |
|
901 |
|
902 // interpolates HSL space, but outputs RGB string (for compatibility) |
|
903 d3.interpolateHsl = function(a, b) { |
|
904 a = d3.hsl(a); |
|
905 b = d3.hsl(b); |
|
906 var h0 = a.h, |
|
907 s0 = a.s, |
|
908 l0 = a.l, |
|
909 h1 = b.h - h0, |
|
910 s1 = b.s - s0, |
|
911 l1 = b.l - l0; |
|
912 return function(t) { |
|
913 return d3_hsl_rgb(h0 + h1 * t, s0 + s1 * t, l0 + l1 * t).toString(); |
|
914 }; |
|
915 }; |
|
916 |
|
917 d3.interpolateArray = function(a, b) { |
|
918 var x = [], |
|
919 c = [], |
|
920 na = a.length, |
|
921 nb = b.length, |
|
922 n0 = Math.min(a.length, b.length), |
|
923 i; |
|
924 for (i = 0; i < n0; ++i) x.push(d3.interpolate(a[i], b[i])); |
|
925 for (; i < na; ++i) c[i] = a[i]; |
|
926 for (; i < nb; ++i) c[i] = b[i]; |
|
927 return function(t) { |
|
928 for (i = 0; i < n0; ++i) c[i] = x[i](t); |
|
929 return c; |
|
930 }; |
|
931 }; |
|
932 |
|
933 d3.interpolateObject = function(a, b) { |
|
934 var i = {}, |
|
935 c = {}, |
|
936 k; |
|
937 for (k in a) { |
|
938 if (k in b) { |
|
939 i[k] = d3_interpolateByName(k)(a[k], b[k]); |
|
940 } else { |
|
941 c[k] = a[k]; |
|
942 } |
|
943 } |
|
944 for (k in b) { |
|
945 if (!(k in a)) { |
|
946 c[k] = b[k]; |
|
947 } |
|
948 } |
|
949 return function(t) { |
|
950 for (k in i) c[k] = i[k](t); |
|
951 return c; |
|
952 }; |
|
953 } |
|
954 |
|
955 var d3_interpolate_number = /[-+]?(?:\d*\.?\d+)(?:[eE][-+]?\d+)?/g; |
|
956 |
|
957 function d3_interpolateByName(n) { |
|
958 return n == "transform" |
|
959 ? d3.interpolateTransform |
|
960 : d3.interpolate; |
|
961 } |
|
962 |
|
963 d3.interpolators = [ |
|
964 d3.interpolateObject, |
|
965 function(a, b) { return (b instanceof Array) && d3.interpolateArray(a, b); }, |
|
966 function(a, b) { return (typeof b === "string") && d3.interpolateString(a + "", b); }, |
|
967 function(a, b) { return (typeof b === "string" ? b in d3_rgb_names || /^(#|rgb\(|hsl\()/.test(b) : b instanceof d3_Rgb || b instanceof d3_Hsl) && d3.interpolateRgb(a + "", b); }, |
|
968 function(a, b) { return (typeof b === "number") && d3.interpolateNumber(+a, b); } |
|
969 ]; |
|
970 function d3_uninterpolateNumber(a, b) { |
|
971 b = b - (a = +a) ? 1 / (b - a) : 0; |
|
972 return function(x) { return (x - a) * b; }; |
|
973 } |
|
974 |
|
975 function d3_uninterpolateClamp(a, b) { |
|
976 b = b - (a = +a) ? 1 / (b - a) : 0; |
|
977 return function(x) { return Math.max(0, Math.min(1, (x - a) * b)); }; |
|
978 } |
|
979 d3.rgb = function(r, g, b) { |
|
980 return arguments.length === 1 |
|
981 ? (r instanceof d3_Rgb ? d3_rgb(r.r, r.g, r.b) |
|
982 : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb)) |
|
983 : d3_rgb(~~r, ~~g, ~~b); |
|
984 }; |
|
985 |
|
986 function d3_rgb(r, g, b) { |
|
987 return new d3_Rgb(r, g, b); |
|
988 } |
|
989 |
|
990 function d3_Rgb(r, g, b) { |
|
991 this.r = r; |
|
992 this.g = g; |
|
993 this.b = b; |
|
994 } |
|
995 |
|
996 d3_Rgb.prototype.brighter = function(k) { |
|
997 k = Math.pow(0.7, arguments.length ? k : 1); |
|
998 var r = this.r, |
|
999 g = this.g, |
|
1000 b = this.b, |
|
1001 i = 30; |
|
1002 if (!r && !g && !b) return d3_rgb(i, i, i); |
|
1003 if (r && r < i) r = i; |
|
1004 if (g && g < i) g = i; |
|
1005 if (b && b < i) b = i; |
|
1006 return d3_rgb( |
|
1007 Math.min(255, Math.floor(r / k)), |
|
1008 Math.min(255, Math.floor(g / k)), |
|
1009 Math.min(255, Math.floor(b / k))); |
|
1010 }; |
|
1011 |
|
1012 d3_Rgb.prototype.darker = function(k) { |
|
1013 k = Math.pow(0.7, arguments.length ? k : 1); |
|
1014 return d3_rgb( |
|
1015 Math.floor(k * this.r), |
|
1016 Math.floor(k * this.g), |
|
1017 Math.floor(k * this.b)); |
|
1018 }; |
|
1019 |
|
1020 d3_Rgb.prototype.hsl = function() { |
|
1021 return d3_rgb_hsl(this.r, this.g, this.b); |
|
1022 }; |
|
1023 |
|
1024 d3_Rgb.prototype.toString = function() { |
|
1025 return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b); |
|
1026 }; |
|
1027 |
|
1028 function d3_rgb_hex(v) { |
|
1029 return v < 0x10 |
|
1030 ? "0" + Math.max(0, v).toString(16) |
|
1031 : Math.min(255, v).toString(16); |
|
1032 } |
|
1033 |
|
1034 function d3_rgb_parse(format, rgb, hsl) { |
|
1035 var r = 0, // red channel; int in [0, 255] |
|
1036 g = 0, // green channel; int in [0, 255] |
|
1037 b = 0, // blue channel; int in [0, 255] |
|
1038 m1, // CSS color specification match |
|
1039 m2, // CSS color specification type (e.g., rgb) |
|
1040 name; |
|
1041 |
|
1042 /* Handle hsl, rgb. */ |
|
1043 m1 = /([a-z]+)\((.*)\)/i.exec(format); |
|
1044 if (m1) { |
|
1045 m2 = m1[2].split(","); |
|
1046 switch (m1[1]) { |
|
1047 case "hsl": { |
|
1048 return hsl( |
|
1049 parseFloat(m2[0]), // degrees |
|
1050 parseFloat(m2[1]) / 100, // percentage |
|
1051 parseFloat(m2[2]) / 100 // percentage |
|
1052 ); |
|
1053 } |
|
1054 case "rgb": { |
|
1055 return rgb( |
|
1056 d3_rgb_parseNumber(m2[0]), |
|
1057 d3_rgb_parseNumber(m2[1]), |
|
1058 d3_rgb_parseNumber(m2[2]) |
|
1059 ); |
|
1060 } |
|
1061 } |
|
1062 } |
|
1063 |
|
1064 /* Named colors. */ |
|
1065 if (name = d3_rgb_names[format]) return rgb(name.r, name.g, name.b); |
|
1066 |
|
1067 /* Hexadecimal colors: #rgb and #rrggbb. */ |
|
1068 if (format != null && format.charAt(0) === "#") { |
|
1069 if (format.length === 4) { |
|
1070 r = format.charAt(1); r += r; |
|
1071 g = format.charAt(2); g += g; |
|
1072 b = format.charAt(3); b += b; |
|
1073 } else if (format.length === 7) { |
|
1074 r = format.substring(1, 3); |
|
1075 g = format.substring(3, 5); |
|
1076 b = format.substring(5, 7); |
|
1077 } |
|
1078 r = parseInt(r, 16); |
|
1079 g = parseInt(g, 16); |
|
1080 b = parseInt(b, 16); |
|
1081 } |
|
1082 |
|
1083 return rgb(r, g, b); |
|
1084 } |
|
1085 |
|
1086 function d3_rgb_hsl(r, g, b) { |
|
1087 var min = Math.min(r /= 255, g /= 255, b /= 255), |
|
1088 max = Math.max(r, g, b), |
|
1089 d = max - min, |
|
1090 h, |
|
1091 s, |
|
1092 l = (max + min) / 2; |
|
1093 if (d) { |
|
1094 s = l < .5 ? d / (max + min) : d / (2 - max - min); |
|
1095 if (r == max) h = (g - b) / d + (g < b ? 6 : 0); |
|
1096 else if (g == max) h = (b - r) / d + 2; |
|
1097 else h = (r - g) / d + 4; |
|
1098 h *= 60; |
|
1099 } else { |
|
1100 s = h = 0; |
|
1101 } |
|
1102 return d3_hsl(h, s, l); |
|
1103 } |
|
1104 |
|
1105 function d3_rgb_parseNumber(c) { // either integer or percentage |
|
1106 var f = parseFloat(c); |
|
1107 return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f; |
|
1108 } |
|
1109 |
|
1110 var d3_rgb_names = { |
|
1111 aliceblue: "#f0f8ff", |
|
1112 antiquewhite: "#faebd7", |
|
1113 aqua: "#00ffff", |
|
1114 aquamarine: "#7fffd4", |
|
1115 azure: "#f0ffff", |
|
1116 beige: "#f5f5dc", |
|
1117 bisque: "#ffe4c4", |
|
1118 black: "#000000", |
|
1119 blanchedalmond: "#ffebcd", |
|
1120 blue: "#0000ff", |
|
1121 blueviolet: "#8a2be2", |
|
1122 brown: "#a52a2a", |
|
1123 burlywood: "#deb887", |
|
1124 cadetblue: "#5f9ea0", |
|
1125 chartreuse: "#7fff00", |
|
1126 chocolate: "#d2691e", |
|
1127 coral: "#ff7f50", |
|
1128 cornflowerblue: "#6495ed", |
|
1129 cornsilk: "#fff8dc", |
|
1130 crimson: "#dc143c", |
|
1131 cyan: "#00ffff", |
|
1132 darkblue: "#00008b", |
|
1133 darkcyan: "#008b8b", |
|
1134 darkgoldenrod: "#b8860b", |
|
1135 darkgray: "#a9a9a9", |
|
1136 darkgreen: "#006400", |
|
1137 darkgrey: "#a9a9a9", |
|
1138 darkkhaki: "#bdb76b", |
|
1139 darkmagenta: "#8b008b", |
|
1140 darkolivegreen: "#556b2f", |
|
1141 darkorange: "#ff8c00", |
|
1142 darkorchid: "#9932cc", |
|
1143 darkred: "#8b0000", |
|
1144 darksalmon: "#e9967a", |
|
1145 darkseagreen: "#8fbc8f", |
|
1146 darkslateblue: "#483d8b", |
|
1147 darkslategray: "#2f4f4f", |
|
1148 darkslategrey: "#2f4f4f", |
|
1149 darkturquoise: "#00ced1", |
|
1150 darkviolet: "#9400d3", |
|
1151 deeppink: "#ff1493", |
|
1152 deepskyblue: "#00bfff", |
|
1153 dimgray: "#696969", |
|
1154 dimgrey: "#696969", |
|
1155 dodgerblue: "#1e90ff", |
|
1156 firebrick: "#b22222", |
|
1157 floralwhite: "#fffaf0", |
|
1158 forestgreen: "#228b22", |
|
1159 fuchsia: "#ff00ff", |
|
1160 gainsboro: "#dcdcdc", |
|
1161 ghostwhite: "#f8f8ff", |
|
1162 gold: "#ffd700", |
|
1163 goldenrod: "#daa520", |
|
1164 gray: "#808080", |
|
1165 green: "#008000", |
|
1166 greenyellow: "#adff2f", |
|
1167 grey: "#808080", |
|
1168 honeydew: "#f0fff0", |
|
1169 hotpink: "#ff69b4", |
|
1170 indianred: "#cd5c5c", |
|
1171 indigo: "#4b0082", |
|
1172 ivory: "#fffff0", |
|
1173 khaki: "#f0e68c", |
|
1174 lavender: "#e6e6fa", |
|
1175 lavenderblush: "#fff0f5", |
|
1176 lawngreen: "#7cfc00", |
|
1177 lemonchiffon: "#fffacd", |
|
1178 lightblue: "#add8e6", |
|
1179 lightcoral: "#f08080", |
|
1180 lightcyan: "#e0ffff", |
|
1181 lightgoldenrodyellow: "#fafad2", |
|
1182 lightgray: "#d3d3d3", |
|
1183 lightgreen: "#90ee90", |
|
1184 lightgrey: "#d3d3d3", |
|
1185 lightpink: "#ffb6c1", |
|
1186 lightsalmon: "#ffa07a", |
|
1187 lightseagreen: "#20b2aa", |
|
1188 lightskyblue: "#87cefa", |
|
1189 lightslategray: "#778899", |
|
1190 lightslategrey: "#778899", |
|
1191 lightsteelblue: "#b0c4de", |
|
1192 lightyellow: "#ffffe0", |
|
1193 lime: "#00ff00", |
|
1194 limegreen: "#32cd32", |
|
1195 linen: "#faf0e6", |
|
1196 magenta: "#ff00ff", |
|
1197 maroon: "#800000", |
|
1198 mediumaquamarine: "#66cdaa", |
|
1199 mediumblue: "#0000cd", |
|
1200 mediumorchid: "#ba55d3", |
|
1201 mediumpurple: "#9370db", |
|
1202 mediumseagreen: "#3cb371", |
|
1203 mediumslateblue: "#7b68ee", |
|
1204 mediumspringgreen: "#00fa9a", |
|
1205 mediumturquoise: "#48d1cc", |
|
1206 mediumvioletred: "#c71585", |
|
1207 midnightblue: "#191970", |
|
1208 mintcream: "#f5fffa", |
|
1209 mistyrose: "#ffe4e1", |
|
1210 moccasin: "#ffe4b5", |
|
1211 navajowhite: "#ffdead", |
|
1212 navy: "#000080", |
|
1213 oldlace: "#fdf5e6", |
|
1214 olive: "#808000", |
|
1215 olivedrab: "#6b8e23", |
|
1216 orange: "#ffa500", |
|
1217 orangered: "#ff4500", |
|
1218 orchid: "#da70d6", |
|
1219 palegoldenrod: "#eee8aa", |
|
1220 palegreen: "#98fb98", |
|
1221 paleturquoise: "#afeeee", |
|
1222 palevioletred: "#db7093", |
|
1223 papayawhip: "#ffefd5", |
|
1224 peachpuff: "#ffdab9", |
|
1225 peru: "#cd853f", |
|
1226 pink: "#ffc0cb", |
|
1227 plum: "#dda0dd", |
|
1228 powderblue: "#b0e0e6", |
|
1229 purple: "#800080", |
|
1230 red: "#ff0000", |
|
1231 rosybrown: "#bc8f8f", |
|
1232 royalblue: "#4169e1", |
|
1233 saddlebrown: "#8b4513", |
|
1234 salmon: "#fa8072", |
|
1235 sandybrown: "#f4a460", |
|
1236 seagreen: "#2e8b57", |
|
1237 seashell: "#fff5ee", |
|
1238 sienna: "#a0522d", |
|
1239 silver: "#c0c0c0", |
|
1240 skyblue: "#87ceeb", |
|
1241 slateblue: "#6a5acd", |
|
1242 slategray: "#708090", |
|
1243 slategrey: "#708090", |
|
1244 snow: "#fffafa", |
|
1245 springgreen: "#00ff7f", |
|
1246 steelblue: "#4682b4", |
|
1247 tan: "#d2b48c", |
|
1248 teal: "#008080", |
|
1249 thistle: "#d8bfd8", |
|
1250 tomato: "#ff6347", |
|
1251 turquoise: "#40e0d0", |
|
1252 violet: "#ee82ee", |
|
1253 wheat: "#f5deb3", |
|
1254 white: "#ffffff", |
|
1255 whitesmoke: "#f5f5f5", |
|
1256 yellow: "#ffff00", |
|
1257 yellowgreen: "#9acd32" |
|
1258 }; |
|
1259 |
|
1260 for (var d3_rgb_name in d3_rgb_names) { |
|
1261 d3_rgb_names[d3_rgb_name] = d3_rgb_parse( |
|
1262 d3_rgb_names[d3_rgb_name], |
|
1263 d3_rgb, |
|
1264 d3_hsl_rgb); |
|
1265 } |
|
1266 d3.hsl = function(h, s, l) { |
|
1267 return arguments.length === 1 |
|
1268 ? (h instanceof d3_Hsl ? d3_hsl(h.h, h.s, h.l) |
|
1269 : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl)) |
|
1270 : d3_hsl(+h, +s, +l); |
|
1271 }; |
|
1272 |
|
1273 function d3_hsl(h, s, l) { |
|
1274 return new d3_Hsl(h, s, l); |
|
1275 } |
|
1276 |
|
1277 function d3_Hsl(h, s, l) { |
|
1278 this.h = h; |
|
1279 this.s = s; |
|
1280 this.l = l; |
|
1281 } |
|
1282 |
|
1283 d3_Hsl.prototype.brighter = function(k) { |
|
1284 k = Math.pow(0.7, arguments.length ? k : 1); |
|
1285 return d3_hsl(this.h, this.s, this.l / k); |
|
1286 }; |
|
1287 |
|
1288 d3_Hsl.prototype.darker = function(k) { |
|
1289 k = Math.pow(0.7, arguments.length ? k : 1); |
|
1290 return d3_hsl(this.h, this.s, k * this.l); |
|
1291 }; |
|
1292 |
|
1293 d3_Hsl.prototype.rgb = function() { |
|
1294 return d3_hsl_rgb(this.h, this.s, this.l); |
|
1295 }; |
|
1296 |
|
1297 d3_Hsl.prototype.toString = function() { |
|
1298 return this.rgb().toString(); |
|
1299 }; |
|
1300 |
|
1301 function d3_hsl_rgb(h, s, l) { |
|
1302 var m1, |
|
1303 m2; |
|
1304 |
|
1305 /* Some simple corrections for h, s and l. */ |
|
1306 h = h % 360; if (h < 0) h += 360; |
|
1307 s = s < 0 ? 0 : s > 1 ? 1 : s; |
|
1308 l = l < 0 ? 0 : l > 1 ? 1 : l; |
|
1309 |
|
1310 /* From FvD 13.37, CSS Color Module Level 3 */ |
|
1311 m2 = l <= .5 ? l * (1 + s) : l + s - l * s; |
|
1312 m1 = 2 * l - m2; |
|
1313 |
|
1314 function v(h) { |
|
1315 if (h > 360) h -= 360; |
|
1316 else if (h < 0) h += 360; |
|
1317 if (h < 60) return m1 + (m2 - m1) * h / 60; |
|
1318 if (h < 180) return m2; |
|
1319 if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60; |
|
1320 return m1; |
|
1321 } |
|
1322 |
|
1323 function vv(h) { |
|
1324 return Math.round(v(h) * 255); |
|
1325 } |
|
1326 |
|
1327 return d3_rgb(vv(h + 120), vv(h), vv(h - 120)); |
|
1328 } |
|
1329 function d3_selection(groups) { |
|
1330 d3_arraySubclass(groups, d3_selectionPrototype); |
|
1331 return groups; |
|
1332 } |
|
1333 |
|
1334 var d3_select = function(s, n) { return n.querySelector(s); }, |
|
1335 d3_selectAll = function(s, n) { return n.querySelectorAll(s); }; |
|
1336 |
|
1337 // Prefer Sizzle, if available. |
|
1338 if (typeof Sizzle === "function") { |
|
1339 d3_select = function(s, n) { return Sizzle(s, n)[0]; }; |
|
1340 d3_selectAll = function(s, n) { return Sizzle.uniqueSort(Sizzle(s, n)); }; |
|
1341 } |
|
1342 |
|
1343 var d3_selectionPrototype = []; |
|
1344 |
|
1345 d3.selection = function() { |
|
1346 return d3_selectionRoot; |
|
1347 }; |
|
1348 |
|
1349 d3.selection.prototype = d3_selectionPrototype; |
|
1350 d3_selectionPrototype.select = function(selector) { |
|
1351 var subgroups = [], |
|
1352 subgroup, |
|
1353 subnode, |
|
1354 group, |
|
1355 node; |
|
1356 |
|
1357 if (typeof selector !== "function") selector = d3_selection_selector(selector); |
|
1358 |
|
1359 for (var j = -1, m = this.length; ++j < m;) { |
|
1360 subgroups.push(subgroup = []); |
|
1361 subgroup.parentNode = (group = this[j]).parentNode; |
|
1362 for (var i = -1, n = group.length; ++i < n;) { |
|
1363 if (node = group[i]) { |
|
1364 subgroup.push(subnode = selector.call(node, node.__data__, i)); |
|
1365 if (subnode && "__data__" in node) subnode.__data__ = node.__data__; |
|
1366 } else { |
|
1367 subgroup.push(null); |
|
1368 } |
|
1369 } |
|
1370 } |
|
1371 |
|
1372 return d3_selection(subgroups); |
|
1373 }; |
|
1374 |
|
1375 function d3_selection_selector(selector) { |
|
1376 return function() { |
|
1377 return d3_select(selector, this); |
|
1378 }; |
|
1379 } |
|
1380 d3_selectionPrototype.selectAll = function(selector) { |
|
1381 var subgroups = [], |
|
1382 subgroup, |
|
1383 node; |
|
1384 |
|
1385 if (typeof selector !== "function") selector = d3_selection_selectorAll(selector); |
|
1386 |
|
1387 for (var j = -1, m = this.length; ++j < m;) { |
|
1388 for (var group = this[j], i = -1, n = group.length; ++i < n;) { |
|
1389 if (node = group[i]) { |
|
1390 subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i))); |
|
1391 subgroup.parentNode = node; |
|
1392 } |
|
1393 } |
|
1394 } |
|
1395 |
|
1396 return d3_selection(subgroups); |
|
1397 }; |
|
1398 |
|
1399 function d3_selection_selectorAll(selector) { |
|
1400 return function() { |
|
1401 return d3_selectAll(selector, this); |
|
1402 }; |
|
1403 } |
|
1404 d3_selectionPrototype.attr = function(name, value) { |
|
1405 name = d3.ns.qualify(name); |
|
1406 |
|
1407 // If no value is specified, return the first value. |
|
1408 if (arguments.length < 2) { |
|
1409 var node = this.node(); |
|
1410 return name.local |
|
1411 ? node.getAttributeNS(name.space, name.local) |
|
1412 : node.getAttribute(name); |
|
1413 } |
|
1414 |
|
1415 function attrNull() { |
|
1416 this.removeAttribute(name); |
|
1417 } |
|
1418 |
|
1419 function attrNullNS() { |
|
1420 this.removeAttributeNS(name.space, name.local); |
|
1421 } |
|
1422 |
|
1423 function attrConstant() { |
|
1424 this.setAttribute(name, value); |
|
1425 } |
|
1426 |
|
1427 function attrConstantNS() { |
|
1428 this.setAttributeNS(name.space, name.local, value); |
|
1429 } |
|
1430 |
|
1431 function attrFunction() { |
|
1432 var x = value.apply(this, arguments); |
|
1433 if (x == null) this.removeAttribute(name); |
|
1434 else this.setAttribute(name, x); |
|
1435 } |
|
1436 |
|
1437 function attrFunctionNS() { |
|
1438 var x = value.apply(this, arguments); |
|
1439 if (x == null) this.removeAttributeNS(name.space, name.local); |
|
1440 else this.setAttributeNS(name.space, name.local, x); |
|
1441 } |
|
1442 |
|
1443 return this.each(value == null |
|
1444 ? (name.local ? attrNullNS : attrNull) : (typeof value === "function" |
|
1445 ? (name.local ? attrFunctionNS : attrFunction) |
|
1446 : (name.local ? attrConstantNS : attrConstant))); |
|
1447 }; |
|
1448 d3_selectionPrototype.classed = function(name, value) { |
|
1449 var names = name.split(d3_selection_classedWhitespace), |
|
1450 n = names.length, |
|
1451 i = -1; |
|
1452 if (arguments.length > 1) { |
|
1453 while (++i < n) d3_selection_classed.call(this, names[i], value); |
|
1454 return this; |
|
1455 } else { |
|
1456 while (++i < n) if (!d3_selection_classed.call(this, names[i])) return false; |
|
1457 return true; |
|
1458 } |
|
1459 }; |
|
1460 |
|
1461 var d3_selection_classedWhitespace = /\s+/g; |
|
1462 |
|
1463 function d3_selection_classed(name, value) { |
|
1464 var re = new RegExp("(^|\\s+)" + d3.requote(name) + "(\\s+|$)", "g"); |
|
1465 |
|
1466 // If no value is specified, return the first value. |
|
1467 if (arguments.length < 2) { |
|
1468 var node = this.node(); |
|
1469 if (c = node.classList) return c.contains(name); |
|
1470 var c = node.className; |
|
1471 re.lastIndex = 0; |
|
1472 return re.test(c.baseVal != null ? c.baseVal : c); |
|
1473 } |
|
1474 |
|
1475 function classedAdd() { |
|
1476 if (c = this.classList) return c.add(name); |
|
1477 var c = this.className, |
|
1478 cb = c.baseVal != null, |
|
1479 cv = cb ? c.baseVal : c; |
|
1480 re.lastIndex = 0; |
|
1481 if (!re.test(cv)) { |
|
1482 cv = d3_collapse(cv + " " + name); |
|
1483 if (cb) c.baseVal = cv; |
|
1484 else this.className = cv; |
|
1485 } |
|
1486 } |
|
1487 |
|
1488 function classedRemove() { |
|
1489 if (c = this.classList) return c.remove(name); |
|
1490 var c = this.className, |
|
1491 cb = c.baseVal != null, |
|
1492 cv = cb ? c.baseVal : c; |
|
1493 cv = d3_collapse(cv.replace(re, " ")); |
|
1494 if (cb) c.baseVal = cv; |
|
1495 else this.className = cv; |
|
1496 } |
|
1497 |
|
1498 function classedFunction() { |
|
1499 (value.apply(this, arguments) |
|
1500 ? classedAdd |
|
1501 : classedRemove).call(this); |
|
1502 } |
|
1503 |
|
1504 return this.each(typeof value === "function" |
|
1505 ? classedFunction : value |
|
1506 ? classedAdd |
|
1507 : classedRemove); |
|
1508 } |
|
1509 d3_selectionPrototype.style = function(name, value, priority) { |
|
1510 if (arguments.length < 3) priority = ""; |
|
1511 |
|
1512 // If no value is specified, return the first value. |
|
1513 if (arguments.length < 2) return window |
|
1514 .getComputedStyle(this.node(), null) |
|
1515 .getPropertyValue(name); |
|
1516 |
|
1517 function styleNull() { |
|
1518 this.style.removeProperty(name); |
|
1519 } |
|
1520 |
|
1521 function styleConstant() { |
|
1522 this.style.setProperty(name, value, priority); |
|
1523 } |
|
1524 |
|
1525 function styleFunction() { |
|
1526 var x = value.apply(this, arguments); |
|
1527 if (x == null) this.style.removeProperty(name); |
|
1528 else this.style.setProperty(name, x, priority); |
|
1529 } |
|
1530 |
|
1531 return this.each(value == null |
|
1532 ? styleNull : (typeof value === "function" |
|
1533 ? styleFunction : styleConstant)); |
|
1534 }; |
|
1535 d3_selectionPrototype.property = function(name, value) { |
|
1536 |
|
1537 // If no value is specified, return the first value. |
|
1538 if (arguments.length < 2) return this.node()[name]; |
|
1539 |
|
1540 function propertyNull() { |
|
1541 delete this[name]; |
|
1542 } |
|
1543 |
|
1544 function propertyConstant() { |
|
1545 this[name] = value; |
|
1546 } |
|
1547 |
|
1548 function propertyFunction() { |
|
1549 var x = value.apply(this, arguments); |
|
1550 if (x == null) delete this[name]; |
|
1551 else this[name] = x; |
|
1552 } |
|
1553 |
|
1554 return this.each(value == null |
|
1555 ? propertyNull : (typeof value === "function" |
|
1556 ? propertyFunction : propertyConstant)); |
|
1557 }; |
|
1558 // TODO addition to get this shortcut |
|
1559 d3_selectionPrototype.datum = function(name, value) { |
|
1560 return arguments.length < 2 |
|
1561 ? this.property("__data__")[name] |
|
1562 : this.property("__data__")[name] = value; |
|
1563 }; |
|
1564 d3_selectionPrototype.text = function(value) { |
|
1565 return arguments.length < 1 ? this.node().textContent |
|
1566 : (this.each(typeof value === "function" |
|
1567 ? function() { this.textContent = value.apply(this, arguments); } |
|
1568 : function() { this.textContent = value; })); |
|
1569 }; |
|
1570 d3_selectionPrototype.html = function(value) { |
|
1571 return arguments.length < 1 ? this.node().innerHTML |
|
1572 : (this.each(typeof value === "function" |
|
1573 ? function() { this.innerHTML = value.apply(this, arguments); } |
|
1574 : function() { this.innerHTML = value; })); |
|
1575 }; |
|
1576 // TODO append(node)? |
|
1577 // TODO append(function)? |
|
1578 d3_selectionPrototype.append = function(name) { |
|
1579 name = d3.ns.qualify(name); |
|
1580 |
|
1581 function append() { |
|
1582 return this.appendChild(document.createElement(name)); |
|
1583 } |
|
1584 |
|
1585 function appendNS() { |
|
1586 return this.appendChild(document.createElementNS(name.space, name.local)); |
|
1587 } |
|
1588 |
|
1589 return this.select(name.local ? appendNS : append); |
|
1590 }; |
|
1591 // TODO insert(node, function)? |
|
1592 // TODO insert(function, string)? |
|
1593 // TODO insert(function, function)? |
|
1594 d3_selectionPrototype.insert = function(name, before) { |
|
1595 name = d3.ns.qualify(name); |
|
1596 |
|
1597 function insert() { |
|
1598 return this.insertBefore( |
|
1599 document.createElement(name), |
|
1600 d3_select(before, this)); |
|
1601 } |
|
1602 |
|
1603 function insertNS() { |
|
1604 return this.insertBefore( |
|
1605 document.createElementNS(name.space, name.local), |
|
1606 d3_select(before, this)); |
|
1607 } |
|
1608 |
|
1609 return this.select(name.local ? insertNS : insert); |
|
1610 }; |
|
1611 // TODO remove(selector)? |
|
1612 // TODO remove(node)? |
|
1613 // TODO remove(function)? |
|
1614 d3_selectionPrototype.remove = function() { |
|
1615 return this.each(function() { |
|
1616 var parent = this.parentNode; |
|
1617 if (parent) parent.removeChild(this); |
|
1618 }); |
|
1619 }; |
|
1620 // TODO data(null) for clearing data? |
|
1621 d3_selectionPrototype.data = function(data, join) { |
|
1622 var enter = [], |
|
1623 update = [], |
|
1624 exit = []; |
|
1625 |
|
1626 function bind(group, groupData) { |
|
1627 var i, |
|
1628 n = group.length, |
|
1629 m = groupData.length, |
|
1630 n0 = Math.min(n, m), |
|
1631 n1 = Math.max(n, m), |
|
1632 updateNodes = [], |
|
1633 enterNodes = [], |
|
1634 exitNodes = [], |
|
1635 node, |
|
1636 nodeData; |
|
1637 |
|
1638 if (join) { |
|
1639 var nodeByKey = {}, |
|
1640 keys = [], |
|
1641 key, |
|
1642 j = groupData.length; |
|
1643 |
|
1644 for (i = -1; ++i < n;) { |
|
1645 key = join.call(node = group[i], node.__data__, i); |
|
1646 if (key in nodeByKey) { |
|
1647 exitNodes[j++] = node; // duplicate key |
|
1648 } else { |
|
1649 nodeByKey[key] = node; |
|
1650 } |
|
1651 keys.push(key); |
|
1652 } |
|
1653 |
|
1654 for (i = -1; ++i < m;) { |
|
1655 node = nodeByKey[key = join.call(groupData, nodeData = groupData[i], i)]; |
|
1656 if (node) { |
|
1657 node.__data__ = nodeData; |
|
1658 updateNodes[i] = node; |
|
1659 enterNodes[i] = exitNodes[i] = null; |
|
1660 } else { |
|
1661 enterNodes[i] = d3_selection_dataNode(nodeData); |
|
1662 updateNodes[i] = exitNodes[i] = null; |
|
1663 } |
|
1664 delete nodeByKey[key]; |
|
1665 } |
|
1666 |
|
1667 for (i = -1; ++i < n;) { |
|
1668 if (keys[i] in nodeByKey) { |
|
1669 exitNodes[i] = group[i]; |
|
1670 } |
|
1671 } |
|
1672 } else { |
|
1673 for (i = -1; ++i < n0;) { |
|
1674 node = group[i]; |
|
1675 nodeData = groupData[i]; |
|
1676 if (node) { |
|
1677 node.__data__ = nodeData; |
|
1678 updateNodes[i] = node; |
|
1679 enterNodes[i] = exitNodes[i] = null; |
|
1680 } else { |
|
1681 enterNodes[i] = d3_selection_dataNode(nodeData); |
|
1682 updateNodes[i] = exitNodes[i] = null; |
|
1683 } |
|
1684 } |
|
1685 for (; i < m; ++i) { |
|
1686 enterNodes[i] = d3_selection_dataNode(groupData[i]); |
|
1687 updateNodes[i] = exitNodes[i] = null; |
|
1688 } |
|
1689 for (; i < n1; ++i) { |
|
1690 exitNodes[i] = group[i]; |
|
1691 enterNodes[i] = updateNodes[i] = null; |
|
1692 } |
|
1693 } |
|
1694 |
|
1695 enterNodes.update |
|
1696 = updateNodes; |
|
1697 |
|
1698 enterNodes.parentNode |
|
1699 = updateNodes.parentNode |
|
1700 = exitNodes.parentNode |
|
1701 = group.parentNode; |
|
1702 |
|
1703 enter.push(enterNodes); |
|
1704 update.push(updateNodes); |
|
1705 exit.push(exitNodes); |
|
1706 } |
|
1707 |
|
1708 var i = -1, |
|
1709 n = this.length, |
|
1710 group; |
|
1711 if (typeof data === "function") { |
|
1712 while (++i < n) { |
|
1713 bind(group = this[i], data.call(group, group.parentNode.__data__, i)); |
|
1714 } |
|
1715 } else { |
|
1716 while (++i < n) { |
|
1717 bind(group = this[i], data); |
|
1718 } |
|
1719 } |
|
1720 |
|
1721 var selection = d3_selection(update); |
|
1722 selection.enter = function() { return d3_selection_enter(enter); }; |
|
1723 selection.exit = function() { return d3_selection(exit); }; |
|
1724 return selection; |
|
1725 }; |
|
1726 |
|
1727 function d3_selection_dataNode(data) { |
|
1728 return {__data__: data}; |
|
1729 } |
|
1730 // TODO preserve null elements to maintain index? |
|
1731 d3_selectionPrototype.filter = function(filter) { |
|
1732 var subgroups = [], |
|
1733 subgroup, |
|
1734 group, |
|
1735 node; |
|
1736 |
|
1737 for (var j = 0, m = this.length; j < m; j++) { |
|
1738 subgroups.push(subgroup = []); |
|
1739 subgroup.parentNode = (group = this[j]).parentNode; |
|
1740 for (var i = 0, n = group.length; i < n; i++) { |
|
1741 if ((node = group[i]) && filter.call(node, node.__data__, i)) { |
|
1742 subgroup.push(node); |
|
1743 } |
|
1744 } |
|
1745 } |
|
1746 |
|
1747 return d3_selection(subgroups); |
|
1748 }; |
|
1749 d3_selectionPrototype.map = function(map) { |
|
1750 return this.each(function() { |
|
1751 this.__data__ = map.apply(this, arguments); |
|
1752 }); |
|
1753 }; |
|
1754 d3_selectionPrototype.sort = function(comparator) { |
|
1755 comparator = d3_selection_sortComparator.apply(this, arguments); |
|
1756 for (var j = 0, m = this.length; j < m; j++) { |
|
1757 for (var group = this[j].sort(comparator), i = 1, n = group.length, prev = group[0]; i < n; i++) { |
|
1758 var node = group[i]; |
|
1759 if (node) { |
|
1760 if (prev) prev.parentNode.insertBefore(node, prev.nextSibling); |
|
1761 prev = node; |
|
1762 } |
|
1763 } |
|
1764 } |
|
1765 return this; |
|
1766 }; |
|
1767 |
|
1768 function d3_selection_sortComparator(comparator) { |
|
1769 if (!arguments.length) comparator = d3.ascending; |
|
1770 return function(a, b) { |
|
1771 return comparator(a && a.__data__, b && b.__data__); |
|
1772 }; |
|
1773 } |
|
1774 // type can be namespaced, e.g., "click.foo" |
|
1775 // listener can be null for removal |
|
1776 d3_selectionPrototype.on = function(type, listener, capture) { |
|
1777 if (arguments.length < 3) capture = false; |
|
1778 |
|
1779 // parse the type specifier |
|
1780 var name = "__on" + type, i = type.indexOf("."); |
|
1781 if (i > 0) type = type.substring(0, i); |
|
1782 |
|
1783 // if called with only one argument, return the current listener |
|
1784 if (arguments.length < 2) return (i = this.node()[name]) && i._; |
|
1785 |
|
1786 // remove the old event listener, and add the new event listener |
|
1787 return this.each(function(d, i) { |
|
1788 var node = this; |
|
1789 |
|
1790 if (node[name]) node.removeEventListener(type, node[name], capture); |
|
1791 if (listener) node.addEventListener(type, node[name] = l, capture); |
|
1792 |
|
1793 // wrapped event listener that preserves i |
|
1794 function l(e) { |
|
1795 var o = d3.event; // Events can be reentrant (e.g., focus). |
|
1796 d3.event = e; |
|
1797 try { |
|
1798 listener.call(node, node.__data__, i); |
|
1799 } finally { |
|
1800 d3.event = o; |
|
1801 } |
|
1802 } |
|
1803 |
|
1804 // stash the unwrapped listener for retrieval |
|
1805 l._ = listener; |
|
1806 }); |
|
1807 }; |
|
1808 d3_selectionPrototype.each = function(callback) { |
|
1809 for (var j = -1, m = this.length; ++j < m;) { |
|
1810 for (var group = this[j], i = -1, n = group.length; ++i < n;) { |
|
1811 var node = group[i]; |
|
1812 if (node) callback.call(node, node.__data__, i, j); |
|
1813 } |
|
1814 } |
|
1815 return this; |
|
1816 }; |
|
1817 // |
|
1818 // Note: assigning to the arguments array simultaneously changes the value of |
|
1819 // the corresponding argument! |
|
1820 // |
|
1821 // TODO The `this` argument probably shouldn't be the first argument to the |
|
1822 // callback, anyway, since it's redundant. However, that will require a major |
|
1823 // version bump due to backwards compatibility, so I'm not changing it right |
|
1824 // away. |
|
1825 // |
|
1826 d3_selectionPrototype.call = function(callback) { |
|
1827 callback.apply(this, (arguments[0] = this, arguments)); |
|
1828 return this; |
|
1829 }; |
|
1830 d3_selectionPrototype.empty = function() { |
|
1831 return !this.node(); |
|
1832 }; |
|
1833 d3_selectionPrototype.node = function(callback) { |
|
1834 for (var j = 0, m = this.length; j < m; j++) { |
|
1835 for (var group = this[j], i = 0, n = group.length; i < n; i++) { |
|
1836 var node = group[i]; |
|
1837 if (node) return node; |
|
1838 } |
|
1839 } |
|
1840 return null; |
|
1841 }; |
|
1842 d3_selectionPrototype.transition = function() { |
|
1843 var subgroups = [], |
|
1844 subgroup, |
|
1845 node; |
|
1846 |
|
1847 for (var j = -1, m = this.length; ++j < m;) { |
|
1848 subgroups.push(subgroup = []); |
|
1849 for (var group = this[j], i = -1, n = group.length; ++i < n;) { |
|
1850 subgroup.push((node = group[i]) ? {node: node, delay: 0, duration: 250} : null); |
|
1851 } |
|
1852 } |
|
1853 |
|
1854 return d3_transition(subgroups, d3_transitionInheritId || ++d3_transitionId, Date.now()); |
|
1855 }; |
|
1856 var d3_selectionRoot = d3_selection([[document]]); |
|
1857 |
|
1858 d3_selectionRoot[0].parentNode = document.documentElement; |
|
1859 |
|
1860 // TODO fast singleton implementation! |
|
1861 // TODO select(function) |
|
1862 d3.select = function(selector) { |
|
1863 return typeof selector === "string" |
|
1864 ? d3_selectionRoot.select(selector) |
|
1865 : d3_selection([[selector]]); // assume node |
|
1866 }; |
|
1867 |
|
1868 // TODO selectAll(function) |
|
1869 d3.selectAll = function(selector) { |
|
1870 return typeof selector === "string" |
|
1871 ? d3_selectionRoot.selectAll(selector) |
|
1872 : d3_selection([d3_array(selector)]); // assume node[] |
|
1873 }; |
|
1874 function d3_selection_enter(selection) { |
|
1875 d3_arraySubclass(selection, d3_selection_enterPrototype); |
|
1876 return selection; |
|
1877 } |
|
1878 |
|
1879 var d3_selection_enterPrototype = []; |
|
1880 |
|
1881 d3_selection_enterPrototype.append = d3_selectionPrototype.append; |
|
1882 d3_selection_enterPrototype.insert = d3_selectionPrototype.insert; |
|
1883 d3_selection_enterPrototype.empty = d3_selectionPrototype.empty; |
|
1884 d3_selection_enterPrototype.node = d3_selectionPrototype.node; |
|
1885 d3_selection_enterPrototype.select = function(selector) { |
|
1886 var subgroups = [], |
|
1887 subgroup, |
|
1888 subnode, |
|
1889 upgroup, |
|
1890 group, |
|
1891 node; |
|
1892 |
|
1893 for (var j = -1, m = this.length; ++j < m;) { |
|
1894 upgroup = (group = this[j]).update; |
|
1895 subgroups.push(subgroup = []); |
|
1896 subgroup.parentNode = group.parentNode; |
|
1897 for (var i = -1, n = group.length; ++i < n;) { |
|
1898 if (node = group[i]) { |
|
1899 subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i)); |
|
1900 subnode.__data__ = node.__data__; |
|
1901 } else { |
|
1902 subgroup.push(null); |
|
1903 } |
|
1904 } |
|
1905 } |
|
1906 |
|
1907 return d3_selection(subgroups); |
|
1908 }; |
|
1909 function d3_transition(groups, id, time) { |
|
1910 d3_arraySubclass(groups, d3_transitionPrototype); |
|
1911 |
|
1912 var tweens = {}, |
|
1913 event = d3.dispatch("start", "end"), |
|
1914 ease = d3_transitionEase; |
|
1915 |
|
1916 groups.id = id; |
|
1917 |
|
1918 groups.time = time; |
|
1919 |
|
1920 groups.tween = function(name, tween) { |
|
1921 if (arguments.length < 2) return tweens[name]; |
|
1922 if (tween == null) delete tweens[name]; |
|
1923 else tweens[name] = tween; |
|
1924 return groups; |
|
1925 }; |
|
1926 |
|
1927 groups.ease = function(value) { |
|
1928 if (!arguments.length) return ease; |
|
1929 ease = typeof value === "function" ? value : d3.ease.apply(d3, arguments); |
|
1930 return groups; |
|
1931 }; |
|
1932 |
|
1933 groups.each = function(type, listener) { |
|
1934 if (arguments.length < 2) return d3_transition_each.call(groups, type); |
|
1935 event.on(type, listener); |
|
1936 return groups; |
|
1937 }; |
|
1938 |
|
1939 d3.timer(function(elapsed) { |
|
1940 groups.each(function(d, i, j) { |
|
1941 var tweened = [], |
|
1942 node = this, |
|
1943 delay = groups[j][i].delay, |
|
1944 duration = groups[j][i].duration, |
|
1945 lock = node.__transition__ || (node.__transition__ = {active: 0, count: 0}); |
|
1946 |
|
1947 ++lock.count; |
|
1948 |
|
1949 delay <= elapsed ? start(elapsed) : d3.timer(start, delay, time); |
|
1950 |
|
1951 function start(elapsed) { |
|
1952 if (lock.active > id) return stop(); |
|
1953 lock.active = id; |
|
1954 |
|
1955 for (var tween in tweens) { |
|
1956 if (tween = tweens[tween].call(node, d, i)) { |
|
1957 tweened.push(tween); |
|
1958 } |
|
1959 } |
|
1960 |
|
1961 event.start.call(node, d, i); |
|
1962 if (!tick(elapsed)) d3.timer(tick, 0, time); |
|
1963 return 1; |
|
1964 } |
|
1965 |
|
1966 function tick(elapsed) { |
|
1967 if (lock.active !== id) return stop(); |
|
1968 |
|
1969 var t = (elapsed - delay) / duration, |
|
1970 e = ease(t), |
|
1971 n = tweened.length; |
|
1972 |
|
1973 while (n > 0) { |
|
1974 tweened[--n].call(node, e); |
|
1975 } |
|
1976 |
|
1977 if (t >= 1) { |
|
1978 stop(); |
|
1979 d3_transitionInheritId = id; |
|
1980 event.end.call(node, d, i); |
|
1981 d3_transitionInheritId = 0; |
|
1982 return 1; |
|
1983 } |
|
1984 } |
|
1985 |
|
1986 function stop() { |
|
1987 if (!--lock.count) delete node.__transition__; |
|
1988 return 1; |
|
1989 } |
|
1990 }); |
|
1991 return 1; |
|
1992 }, 0, time); |
|
1993 |
|
1994 return groups; |
|
1995 } |
|
1996 |
|
1997 var d3_transitionRemove = {}; |
|
1998 |
|
1999 function d3_transitionNull(d, i, a) { |
|
2000 return a != "" && d3_transitionRemove; |
|
2001 } |
|
2002 |
|
2003 function d3_transitionTween(name, b) { |
|
2004 var interpolate = d3_interpolateByName(name); |
|
2005 |
|
2006 function transitionFunction(d, i, a) { |
|
2007 var v = b.call(this, d, i); |
|
2008 return v == null |
|
2009 ? a != "" && d3_transitionRemove |
|
2010 : a != v && interpolate(a, v); |
|
2011 } |
|
2012 |
|
2013 function transitionString(d, i, a) { |
|
2014 return a != b && interpolate(a, b); |
|
2015 } |
|
2016 |
|
2017 return typeof b === "function" ? transitionFunction |
|
2018 : b == null ? d3_transitionNull |
|
2019 : (b += "", transitionString); |
|
2020 } |
|
2021 |
|
2022 var d3_transitionPrototype = [], |
|
2023 d3_transitionId = 0, |
|
2024 d3_transitionInheritId = 0, |
|
2025 d3_transitionEase = d3.ease("cubic-in-out"); |
|
2026 |
|
2027 d3_transitionPrototype.call = d3_selectionPrototype.call; |
|
2028 |
|
2029 d3.transition = function() { |
|
2030 return d3_selectionRoot.transition(); |
|
2031 }; |
|
2032 |
|
2033 d3.transition.prototype = d3_transitionPrototype; |
|
2034 d3_transitionPrototype.select = function(selector) { |
|
2035 var subgroups = [], |
|
2036 subgroup, |
|
2037 subnode, |
|
2038 node; |
|
2039 |
|
2040 if (typeof selector !== "function") selector = d3_selection_selector(selector); |
|
2041 |
|
2042 for (var j = -1, m = this.length; ++j < m;) { |
|
2043 subgroups.push(subgroup = []); |
|
2044 for (var group = this[j], i = -1, n = group.length; ++i < n;) { |
|
2045 if ((node = group[i]) && (subnode = selector.call(node.node, node.node.__data__, i))) { |
|
2046 if ("__data__" in node.node) subnode.__data__ = node.node.__data__; |
|
2047 subgroup.push({node: subnode, delay: node.delay, duration: node.duration}); |
|
2048 } else { |
|
2049 subgroup.push(null); |
|
2050 } |
|
2051 } |
|
2052 } |
|
2053 |
|
2054 return d3_transition(subgroups, this.id, this.time).ease(this.ease()); |
|
2055 }; |
|
2056 d3_transitionPrototype.selectAll = function(selector) { |
|
2057 var subgroups = [], |
|
2058 subgroup, |
|
2059 subnodes, |
|
2060 node; |
|
2061 |
|
2062 if (typeof selector !== "function") selector = d3_selection_selectorAll(selector); |
|
2063 |
|
2064 for (var j = -1, m = this.length; ++j < m;) { |
|
2065 for (var group = this[j], i = -1, n = group.length; ++i < n;) { |
|
2066 if (node = group[i]) { |
|
2067 subnodes = selector.call(node.node, node.node.__data__, i); |
|
2068 subgroups.push(subgroup = []); |
|
2069 for (var k = -1, o = subnodes.length; ++k < o;) { |
|
2070 subgroup.push({node: subnodes[k], delay: node.delay, duration: node.duration}); |
|
2071 } |
|
2072 } |
|
2073 } |
|
2074 } |
|
2075 |
|
2076 return d3_transition(subgroups, this.id, this.time).ease(this.ease()); |
|
2077 }; |
|
2078 d3_transitionPrototype.attr = function(name, value) { |
|
2079 return this.attrTween(name, d3_transitionTween(name, value)); |
|
2080 }; |
|
2081 |
|
2082 d3_transitionPrototype.attrTween = function(nameNS, tween) { |
|
2083 var name = d3.ns.qualify(nameNS); |
|
2084 |
|
2085 function attrTween(d, i) { |
|
2086 var f = tween.call(this, d, i, this.getAttribute(name)); |
|
2087 return f === d3_transitionRemove |
|
2088 ? (this.removeAttribute(name), null) |
|
2089 : f && function(t) { this.setAttribute(name, f(t)); }; |
|
2090 } |
|
2091 |
|
2092 function attrTweenNS(d, i) { |
|
2093 var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local)); |
|
2094 return f === d3_transitionRemove |
|
2095 ? (this.removeAttributeNS(name.space, name.local), null) |
|
2096 : f && function(t) { this.setAttributeNS(name.space, name.local, f(t)); }; |
|
2097 } |
|
2098 |
|
2099 return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween); |
|
2100 }; |
|
2101 d3_transitionPrototype.style = function(name, value, priority) { |
|
2102 if (arguments.length < 3) priority = ""; |
|
2103 return this.styleTween(name, d3_transitionTween(name, value), priority); |
|
2104 }; |
|
2105 |
|
2106 d3_transitionPrototype.styleTween = function(name, tween, priority) { |
|
2107 if (arguments.length < 3) priority = ""; |
|
2108 return this.tween("style." + name, function(d, i) { |
|
2109 var f = tween.call(this, d, i, window.getComputedStyle(this, null).getPropertyValue(name)); |
|
2110 return f === d3_transitionRemove |
|
2111 ? (this.style.removeProperty(name), null) |
|
2112 : f && function(t) { this.style.setProperty(name, f(t), priority); }; |
|
2113 }); |
|
2114 }; |
|
2115 d3_transitionPrototype.text = function(value) { |
|
2116 return this.tween("text", function(d, i) { |
|
2117 this.textContent = typeof value === "function" |
|
2118 ? value.call(this, d, i) |
|
2119 : value; |
|
2120 }); |
|
2121 }; |
|
2122 d3_transitionPrototype.remove = function() { |
|
2123 return this.each("end", function() { |
|
2124 var p; |
|
2125 if (!this.__transition__ && (p = this.parentNode)) p.removeChild(this); |
|
2126 }); |
|
2127 }; |
|
2128 d3_transitionPrototype.delay = function(value) { |
|
2129 var groups = this; |
|
2130 return groups.each(typeof value === "function" |
|
2131 ? function(d, i, j) { groups[j][i].delay = +value.apply(this, arguments); } |
|
2132 : (value = +value, function(d, i, j) { groups[j][i].delay = value; })); |
|
2133 }; |
|
2134 d3_transitionPrototype.duration = function(value) { |
|
2135 var groups = this; |
|
2136 return groups.each(typeof value === "function" |
|
2137 ? function(d, i, j) { groups[j][i].duration = +value.apply(this, arguments); } |
|
2138 : (value = +value, function(d, i, j) { groups[j][i].duration = value; })); |
|
2139 }; |
|
2140 function d3_transition_each(callback) { |
|
2141 for (var j = 0, m = this.length; j < m; j++) { |
|
2142 for (var group = this[j], i = 0, n = group.length; i < n; i++) { |
|
2143 var node = group[i]; |
|
2144 if (node) callback.call(node = node.node, node.__data__, i, j); |
|
2145 } |
|
2146 } |
|
2147 return this; |
|
2148 } |
|
2149 d3_transitionPrototype.transition = function() { |
|
2150 return this.select(d3_this); |
|
2151 }; |
|
2152 var d3_timer_queue = null, |
|
2153 d3_timer_interval, // is an interval (or frame) active? |
|
2154 d3_timer_timeout; // is a timeout active? |
|
2155 |
|
2156 // The timer will continue to fire until callback returns true. |
|
2157 d3.timer = function(callback, delay, then) { |
|
2158 var found = false, |
|
2159 t0, |
|
2160 t1 = d3_timer_queue; |
|
2161 |
|
2162 if (arguments.length < 3) { |
|
2163 if (arguments.length < 2) delay = 0; |
|
2164 else if (!isFinite(delay)) return; |
|
2165 then = Date.now(); |
|
2166 } |
|
2167 |
|
2168 // See if the callback's already in the queue. |
|
2169 while (t1) { |
|
2170 if (t1.callback === callback) { |
|
2171 t1.then = then; |
|
2172 t1.delay = delay; |
|
2173 found = true; |
|
2174 break; |
|
2175 } |
|
2176 t0 = t1; |
|
2177 t1 = t1.next; |
|
2178 } |
|
2179 |
|
2180 // Otherwise, add the callback to the queue. |
|
2181 if (!found) d3_timer_queue = { |
|
2182 callback: callback, |
|
2183 then: then, |
|
2184 delay: delay, |
|
2185 next: d3_timer_queue |
|
2186 }; |
|
2187 |
|
2188 // Start animatin'! |
|
2189 if (!d3_timer_interval) { |
|
2190 d3_timer_timeout = clearTimeout(d3_timer_timeout); |
|
2191 d3_timer_interval = 1; |
|
2192 d3_timer_frame(d3_timer_step); |
|
2193 } |
|
2194 } |
|
2195 |
|
2196 function d3_timer_step() { |
|
2197 var elapsed, |
|
2198 now = Date.now(), |
|
2199 t1 = d3_timer_queue; |
|
2200 |
|
2201 while (t1) { |
|
2202 elapsed = now - t1.then; |
|
2203 if (elapsed >= t1.delay) t1.flush = t1.callback(elapsed); |
|
2204 t1 = t1.next; |
|
2205 } |
|
2206 |
|
2207 var delay = d3_timer_flush() - now; |
|
2208 if (delay > 24) { |
|
2209 if (isFinite(delay)) { |
|
2210 clearTimeout(d3_timer_timeout); |
|
2211 d3_timer_timeout = setTimeout(d3_timer_step, delay); |
|
2212 } |
|
2213 d3_timer_interval = 0; |
|
2214 } else { |
|
2215 d3_timer_interval = 1; |
|
2216 d3_timer_frame(d3_timer_step); |
|
2217 } |
|
2218 } |
|
2219 |
|
2220 d3.timer.flush = function() { |
|
2221 var elapsed, |
|
2222 now = Date.now(), |
|
2223 t1 = d3_timer_queue; |
|
2224 |
|
2225 while (t1) { |
|
2226 elapsed = now - t1.then; |
|
2227 if (!t1.delay) t1.flush = t1.callback(elapsed); |
|
2228 t1 = t1.next; |
|
2229 } |
|
2230 |
|
2231 d3_timer_flush(); |
|
2232 }; |
|
2233 |
|
2234 // Flush after callbacks, to avoid concurrent queue modification. |
|
2235 function d3_timer_flush() { |
|
2236 var t0 = null, |
|
2237 t1 = d3_timer_queue, |
|
2238 then = Infinity; |
|
2239 while (t1) { |
|
2240 if (t1.flush) { |
|
2241 t1 = t0 ? t0.next = t1.next : d3_timer_queue = t1.next; |
|
2242 } else { |
|
2243 then = Math.min(then, t1.then + t1.delay); |
|
2244 t1 = (t0 = t1).next; |
|
2245 } |
|
2246 } |
|
2247 return then; |
|
2248 } |
|
2249 |
|
2250 var d3_timer_frame = window.requestAnimationFrame |
|
2251 || window.webkitRequestAnimationFrame |
|
2252 || window.mozRequestAnimationFrame |
|
2253 || window.oRequestAnimationFrame |
|
2254 || window.msRequestAnimationFrame |
|
2255 || function(callback) { setTimeout(callback, 17); }; |
|
2256 d3.transform = function(string) { |
|
2257 d3_transformG.setAttribute("transform", string); |
|
2258 return new d3_transform(d3_transformG.transform.baseVal.consolidate().matrix); |
|
2259 }; |
|
2260 |
|
2261 // Compute x-scale and normalize the first row. |
|
2262 // Compute shear and make second row orthogonal to first. |
|
2263 // Compute y-scale and normalize the second row. |
|
2264 // Finally, compute the rotation. |
|
2265 function d3_transform(m) { |
|
2266 var r0 = [m.a, m.b], |
|
2267 r1 = [m.c, m.d], |
|
2268 kx = d3_transformNormalize(r0), |
|
2269 kz = d3_transformDot(r0, r1), |
|
2270 ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)); |
|
2271 this.translate = [m.e, m.f]; |
|
2272 this.rotate = Math.atan2(m.b, m.a) * d3_transformDegrees; |
|
2273 this.scale = [kx, ky || 0]; |
|
2274 this.skew = ky ? kz / ky * d3_transformDegrees : 0; |
|
2275 }; |
|
2276 |
|
2277 d3_transform.prototype.toString = function() { |
|
2278 return "translate(" + this.translate |
|
2279 + ")rotate(" + this.rotate |
|
2280 + ")skewX(" + this.skew |
|
2281 + ")scale(" + this.scale |
|
2282 + ")"; |
|
2283 }; |
|
2284 |
|
2285 function d3_transformDot(a, b) { |
|
2286 return a[0] * b[0] + a[1] * b[1]; |
|
2287 } |
|
2288 |
|
2289 function d3_transformNormalize(a) { |
|
2290 var k = Math.sqrt(d3_transformDot(a, a)); |
|
2291 a[0] /= k; |
|
2292 a[1] /= k; |
|
2293 return k; |
|
2294 } |
|
2295 |
|
2296 function d3_transformCombine(a, b, k) { |
|
2297 a[0] += k * b[0]; |
|
2298 a[1] += k * b[1]; |
|
2299 return a; |
|
2300 } |
|
2301 |
|
2302 var d3_transformG = document.createElementNS(d3.ns.prefix.svg, "g"), |
|
2303 d3_transformDegrees = 180 / Math.PI; |
|
2304 function d3_noop() {} |
|
2305 d3.scale = {}; |
|
2306 |
|
2307 function d3_scaleExtent(domain) { |
|
2308 var start = domain[0], stop = domain[domain.length - 1]; |
|
2309 return start < stop ? [start, stop] : [stop, start]; |
|
2310 } |
|
2311 function d3_scale_nice(domain, nice) { |
|
2312 var i0 = 0, |
|
2313 i1 = domain.length - 1, |
|
2314 x0 = domain[i0], |
|
2315 x1 = domain[i1], |
|
2316 dx; |
|
2317 |
|
2318 if (x1 < x0) { |
|
2319 dx = i0; i0 = i1; i1 = dx; |
|
2320 dx = x0; x0 = x1; x1 = dx; |
|
2321 } |
|
2322 |
|
2323 if (dx = x1 - x0) { |
|
2324 nice = nice(dx); |
|
2325 domain[i0] = nice.floor(x0); |
|
2326 domain[i1] = nice.ceil(x1); |
|
2327 } |
|
2328 |
|
2329 return domain; |
|
2330 } |
|
2331 |
|
2332 function d3_scale_niceDefault() { |
|
2333 return Math; |
|
2334 } |
|
2335 d3.scale.linear = function() { |
|
2336 return d3_scale_linear([0, 1], [0, 1], d3.interpolate, false); |
|
2337 }; |
|
2338 |
|
2339 function d3_scale_linear(domain, range, interpolate, clamp) { |
|
2340 var output, |
|
2341 input; |
|
2342 |
|
2343 function rescale() { |
|
2344 var linear = domain.length == 2 ? d3_scale_bilinear : d3_scale_polylinear, |
|
2345 uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber; |
|
2346 output = linear(domain, range, uninterpolate, interpolate); |
|
2347 input = linear(range, domain, uninterpolate, d3.interpolate); |
|
2348 return scale; |
|
2349 } |
|
2350 |
|
2351 function scale(x) { |
|
2352 return output(x); |
|
2353 } |
|
2354 |
|
2355 // Note: requires range is coercible to number! |
|
2356 scale.invert = function(y) { |
|
2357 return input(y); |
|
2358 }; |
|
2359 |
|
2360 scale.domain = function(x) { |
|
2361 if (!arguments.length) return domain; |
|
2362 domain = x.map(Number); |
|
2363 return rescale(); |
|
2364 }; |
|
2365 |
|
2366 scale.range = function(x) { |
|
2367 if (!arguments.length) return range; |
|
2368 range = x; |
|
2369 return rescale(); |
|
2370 }; |
|
2371 |
|
2372 scale.rangeRound = function(x) { |
|
2373 return scale.range(x).interpolate(d3.interpolateRound); |
|
2374 }; |
|
2375 |
|
2376 scale.clamp = function(x) { |
|
2377 if (!arguments.length) return clamp; |
|
2378 clamp = x; |
|
2379 return rescale(); |
|
2380 }; |
|
2381 |
|
2382 scale.interpolate = function(x) { |
|
2383 if (!arguments.length) return interpolate; |
|
2384 interpolate = x; |
|
2385 return rescale(); |
|
2386 }; |
|
2387 |
|
2388 scale.ticks = function(m) { |
|
2389 return d3_scale_linearTicks(domain, m); |
|
2390 }; |
|
2391 |
|
2392 scale.tickFormat = function(m) { |
|
2393 return d3_scale_linearTickFormat(domain, m); |
|
2394 }; |
|
2395 |
|
2396 scale.nice = function() { |
|
2397 d3_scale_nice(domain, d3_scale_linearNice); |
|
2398 return rescale(); |
|
2399 }; |
|
2400 |
|
2401 scale.copy = function() { |
|
2402 return d3_scale_linear(domain, range, interpolate, clamp); |
|
2403 }; |
|
2404 |
|
2405 return rescale(); |
|
2406 }; |
|
2407 |
|
2408 function d3_scale_linearRebind(scale, linear) { |
|
2409 scale.range = d3.rebind(scale, linear.range); |
|
2410 scale.rangeRound = d3.rebind(scale, linear.rangeRound); |
|
2411 scale.interpolate = d3.rebind(scale, linear.interpolate); |
|
2412 scale.clamp = d3.rebind(scale, linear.clamp); |
|
2413 return scale; |
|
2414 } |
|
2415 |
|
2416 function d3_scale_linearNice(dx) { |
|
2417 dx = Math.pow(10, Math.round(Math.log(dx) / Math.LN10) - 1); |
|
2418 return { |
|
2419 floor: function(x) { return Math.floor(x / dx) * dx; }, |
|
2420 ceil: function(x) { return Math.ceil(x / dx) * dx; } |
|
2421 }; |
|
2422 } |
|
2423 |
|
2424 // TODO Dates? Ugh. |
|
2425 function d3_scale_linearTickRange(domain, m) { |
|
2426 var extent = d3_scaleExtent(domain), |
|
2427 span = extent[1] - extent[0], |
|
2428 step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), |
|
2429 err = m / span * step; |
|
2430 |
|
2431 // Filter ticks to get closer to the desired count. |
|
2432 if (err <= .15) step *= 10; |
|
2433 else if (err <= .35) step *= 5; |
|
2434 else if (err <= .75) step *= 2; |
|
2435 |
|
2436 // Round start and stop values to step interval. |
|
2437 extent[0] = Math.ceil(extent[0] / step) * step; |
|
2438 extent[1] = Math.floor(extent[1] / step) * step + step * .5; // inclusive |
|
2439 extent[2] = step; |
|
2440 return extent; |
|
2441 } |
|
2442 |
|
2443 function d3_scale_linearTicks(domain, m) { |
|
2444 return d3.range.apply(d3, d3_scale_linearTickRange(domain, m)); |
|
2445 } |
|
2446 |
|
2447 function d3_scale_linearTickFormat(domain, m) { |
|
2448 return d3.format(",." + Math.max(0, -Math.floor(Math.log(d3_scale_linearTickRange(domain, m)[2]) / Math.LN10 + .01)) + "f"); |
|
2449 } |
|
2450 function d3_scale_bilinear(domain, range, uninterpolate, interpolate) { |
|
2451 var u = uninterpolate(domain[0], domain[1]), |
|
2452 i = interpolate(range[0], range[1]); |
|
2453 return function(x) { |
|
2454 return i(u(x)); |
|
2455 }; |
|
2456 } |
|
2457 function d3_scale_polylinear(domain, range, uninterpolate, interpolate) { |
|
2458 var u = [], |
|
2459 i = [], |
|
2460 j = 0, |
|
2461 n = domain.length; |
|
2462 |
|
2463 while (++j < n) { |
|
2464 u.push(uninterpolate(domain[j - 1], domain[j])); |
|
2465 i.push(interpolate(range[j - 1], range[j])); |
|
2466 } |
|
2467 |
|
2468 return function(x) { |
|
2469 var j = d3.bisect(domain, x, 1, domain.length - 1) - 1; |
|
2470 return i[j](u[j](x)); |
|
2471 }; |
|
2472 } |
|
2473 d3.scale.log = function() { |
|
2474 return d3_scale_log(d3.scale.linear(), d3_scale_logp); |
|
2475 }; |
|
2476 |
|
2477 function d3_scale_log(linear, log) { |
|
2478 var pow = log.pow; |
|
2479 |
|
2480 function scale(x) { |
|
2481 return linear(log(x)); |
|
2482 } |
|
2483 |
|
2484 scale.invert = function(x) { |
|
2485 return pow(linear.invert(x)); |
|
2486 }; |
|
2487 |
|
2488 scale.domain = function(x) { |
|
2489 if (!arguments.length) return linear.domain().map(pow); |
|
2490 log = x[0] < 0 ? d3_scale_logn : d3_scale_logp; |
|
2491 pow = log.pow; |
|
2492 linear.domain(x.map(log)); |
|
2493 return scale; |
|
2494 }; |
|
2495 |
|
2496 scale.nice = function() { |
|
2497 linear.domain(d3_scale_nice(linear.domain(), d3_scale_niceDefault)); |
|
2498 return scale; |
|
2499 }; |
|
2500 |
|
2501 scale.ticks = function() { |
|
2502 var extent = d3_scaleExtent(linear.domain()), |
|
2503 ticks = []; |
|
2504 if (extent.every(isFinite)) { |
|
2505 var i = Math.floor(extent[0]), |
|
2506 j = Math.ceil(extent[1]), |
|
2507 u = Math.round(pow(extent[0])), |
|
2508 v = Math.round(pow(extent[1])); |
|
2509 if (log === d3_scale_logn) { |
|
2510 ticks.push(pow(i)); |
|
2511 for (; i++ < j;) for (var k = 9; k > 0; k--) ticks.push(pow(i) * k); |
|
2512 } else { |
|
2513 for (; i < j; i++) for (var k = 1; k < 10; k++) ticks.push(pow(i) * k); |
|
2514 ticks.push(pow(i)); |
|
2515 } |
|
2516 for (i = 0; ticks[i] < u; i++) {} // strip small values |
|
2517 for (j = ticks.length; ticks[j - 1] > v; j--) {} // strip big values |
|
2518 ticks = ticks.slice(i, j); |
|
2519 } |
|
2520 return ticks; |
|
2521 }; |
|
2522 |
|
2523 scale.tickFormat = function(n, format) { |
|
2524 if (arguments.length < 2) format = d3_scale_logFormat; |
|
2525 if (arguments.length < 1) return format; |
|
2526 var k = n / scale.ticks().length, |
|
2527 f = log === d3_scale_logn ? (e = -1e-15, Math.floor) : (e = 1e-15, Math.ceil), |
|
2528 e; |
|
2529 return function(d) { |
|
2530 return d / pow(f(log(d) + e)) < k ? format(d) : ""; |
|
2531 }; |
|
2532 }; |
|
2533 |
|
2534 scale.copy = function() { |
|
2535 return d3_scale_log(linear.copy(), log); |
|
2536 }; |
|
2537 |
|
2538 return d3_scale_linearRebind(scale, linear); |
|
2539 }; |
|
2540 |
|
2541 var d3_scale_logFormat = d3.format("e"); |
|
2542 |
|
2543 function d3_scale_logp(x) { |
|
2544 return Math.log(x) / Math.LN10; |
|
2545 } |
|
2546 |
|
2547 function d3_scale_logn(x) { |
|
2548 return -Math.log(-x) / Math.LN10; |
|
2549 } |
|
2550 |
|
2551 d3_scale_logp.pow = function(x) { |
|
2552 return Math.pow(10, x); |
|
2553 }; |
|
2554 |
|
2555 d3_scale_logn.pow = function(x) { |
|
2556 return -Math.pow(10, -x); |
|
2557 }; |
|
2558 d3.scale.pow = function() { |
|
2559 return d3_scale_pow(d3.scale.linear(), 1); |
|
2560 }; |
|
2561 |
|
2562 function d3_scale_pow(linear, exponent) { |
|
2563 var powp = d3_scale_powPow(exponent), |
|
2564 powb = d3_scale_powPow(1 / exponent); |
|
2565 |
|
2566 function scale(x) { |
|
2567 return linear(powp(x)); |
|
2568 } |
|
2569 |
|
2570 scale.invert = function(x) { |
|
2571 return powb(linear.invert(x)); |
|
2572 }; |
|
2573 |
|
2574 scale.domain = function(x) { |
|
2575 if (!arguments.length) return linear.domain().map(powb); |
|
2576 linear.domain(x.map(powp)); |
|
2577 return scale; |
|
2578 }; |
|
2579 |
|
2580 scale.ticks = function(m) { |
|
2581 return d3_scale_linearTicks(scale.domain(), m); |
|
2582 }; |
|
2583 |
|
2584 scale.tickFormat = function(m) { |
|
2585 return d3_scale_linearTickFormat(scale.domain(), m); |
|
2586 }; |
|
2587 |
|
2588 scale.nice = function() { |
|
2589 return scale.domain(d3_scale_nice(scale.domain(), d3_scale_linearNice)); |
|
2590 }; |
|
2591 |
|
2592 scale.exponent = function(x) { |
|
2593 if (!arguments.length) return exponent; |
|
2594 var domain = scale.domain(); |
|
2595 powp = d3_scale_powPow(exponent = x); |
|
2596 powb = d3_scale_powPow(1 / exponent); |
|
2597 return scale.domain(domain); |
|
2598 }; |
|
2599 |
|
2600 scale.copy = function() { |
|
2601 return d3_scale_pow(linear.copy(), exponent); |
|
2602 }; |
|
2603 |
|
2604 return d3_scale_linearRebind(scale, linear); |
|
2605 }; |
|
2606 |
|
2607 function d3_scale_powPow(e) { |
|
2608 return function(x) { |
|
2609 return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e); |
|
2610 }; |
|
2611 } |
|
2612 d3.scale.sqrt = function() { |
|
2613 return d3.scale.pow().exponent(.5); |
|
2614 }; |
|
2615 d3.scale.ordinal = function() { |
|
2616 return d3_scale_ordinal([], {t: "range", x: []}); |
|
2617 }; |
|
2618 |
|
2619 function d3_scale_ordinal(domain, ranger) { |
|
2620 var index, |
|
2621 range, |
|
2622 rangeBand; |
|
2623 |
|
2624 function scale(x) { |
|
2625 return range[((index[x] || (index[x] = domain.push(x))) - 1) % range.length]; |
|
2626 } |
|
2627 |
|
2628 function steps(start, step) { |
|
2629 return d3.range(domain.length).map(function(i) { return start + step * i; }); |
|
2630 } |
|
2631 |
|
2632 scale.domain = function(x) { |
|
2633 if (!arguments.length) return domain; |
|
2634 domain = []; |
|
2635 index = {}; |
|
2636 var i = -1, n = x.length, xi; |
|
2637 while (++i < n) if (!index[xi = x[i]]) index[xi] = domain.push(xi); |
|
2638 return scale[ranger.t](ranger.x, ranger.p); |
|
2639 }; |
|
2640 |
|
2641 scale.range = function(x) { |
|
2642 if (!arguments.length) return range; |
|
2643 range = x; |
|
2644 rangeBand = 0; |
|
2645 ranger = {t: "range", x: x}; |
|
2646 return scale; |
|
2647 }; |
|
2648 |
|
2649 scale.rangePoints = function(x, padding) { |
|
2650 if (arguments.length < 2) padding = 0; |
|
2651 var start = x[0], |
|
2652 stop = x[1], |
|
2653 step = (stop - start) / (domain.length - 1 + padding); |
|
2654 range = steps(domain.length < 2 ? (start + stop) / 2 : start + step * padding / 2, step); |
|
2655 rangeBand = 0; |
|
2656 ranger = {t: "rangePoints", x: x, p: padding}; |
|
2657 return scale; |
|
2658 }; |
|
2659 |
|
2660 scale.rangeBands = function(x, padding) { |
|
2661 if (arguments.length < 2) padding = 0; |
|
2662 var start = x[0], |
|
2663 stop = x[1], |
|
2664 step = (stop - start) / (domain.length + padding); |
|
2665 range = steps(start + step * padding, step); |
|
2666 rangeBand = step * (1 - padding); |
|
2667 ranger = {t: "rangeBands", x: x, p: padding}; |
|
2668 return scale; |
|
2669 }; |
|
2670 |
|
2671 scale.rangeRoundBands = function(x, padding) { |
|
2672 if (arguments.length < 2) padding = 0; |
|
2673 var start = x[0], |
|
2674 stop = x[1], |
|
2675 step = Math.floor((stop - start) / (domain.length + padding)); |
|
2676 range = steps(start + Math.round((stop - start - (domain.length - padding) * step) / 2), step); |
|
2677 rangeBand = Math.round(step * (1 - padding)); |
|
2678 ranger = {t: "rangeRoundBands", x: x, p: padding}; |
|
2679 return scale; |
|
2680 }; |
|
2681 |
|
2682 scale.rangeBand = function() { |
|
2683 return rangeBand; |
|
2684 }; |
|
2685 |
|
2686 scale.copy = function() { |
|
2687 return d3_scale_ordinal(domain, ranger); |
|
2688 }; |
|
2689 |
|
2690 return scale.domain(domain); |
|
2691 }; |
|
2692 /* |
|
2693 * This product includes color specifications and designs developed by Cynthia |
|
2694 * Brewer (http://colorbrewer.org/). See lib/colorbrewer for more information. |
|
2695 */ |
|
2696 |
|
2697 d3.scale.category10 = function() { |
|
2698 return d3.scale.ordinal().range(d3_category10); |
|
2699 }; |
|
2700 |
|
2701 d3.scale.category20 = function() { |
|
2702 return d3.scale.ordinal().range(d3_category20); |
|
2703 }; |
|
2704 |
|
2705 d3.scale.category20b = function() { |
|
2706 return d3.scale.ordinal().range(d3_category20b); |
|
2707 }; |
|
2708 |
|
2709 d3.scale.category20c = function() { |
|
2710 return d3.scale.ordinal().range(d3_category20c); |
|
2711 }; |
|
2712 |
|
2713 var d3_category10 = [ |
|
2714 "#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", |
|
2715 "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf" |
|
2716 ]; |
|
2717 |
|
2718 var d3_category20 = [ |
|
2719 "#1f77b4", "#aec7e8", |
|
2720 "#ff7f0e", "#ffbb78", |
|
2721 "#2ca02c", "#98df8a", |
|
2722 "#d62728", "#ff9896", |
|
2723 "#9467bd", "#c5b0d5", |
|
2724 "#8c564b", "#c49c94", |
|
2725 "#e377c2", "#f7b6d2", |
|
2726 "#7f7f7f", "#c7c7c7", |
|
2727 "#bcbd22", "#dbdb8d", |
|
2728 "#17becf", "#9edae5" |
|
2729 ]; |
|
2730 |
|
2731 var d3_category20b = [ |
|
2732 "#393b79", "#5254a3", "#6b6ecf", "#9c9ede", |
|
2733 "#637939", "#8ca252", "#b5cf6b", "#cedb9c", |
|
2734 "#8c6d31", "#bd9e39", "#e7ba52", "#e7cb94", |
|
2735 "#843c39", "#ad494a", "#d6616b", "#e7969c", |
|
2736 "#7b4173", "#a55194", "#ce6dbd", "#de9ed6" |
|
2737 ]; |
|
2738 |
|
2739 var d3_category20c = [ |
|
2740 "#3182bd", "#6baed6", "#9ecae1", "#c6dbef", |
|
2741 "#e6550d", "#fd8d3c", "#fdae6b", "#fdd0a2", |
|
2742 "#31a354", "#74c476", "#a1d99b", "#c7e9c0", |
|
2743 "#756bb1", "#9e9ac8", "#bcbddc", "#dadaeb", |
|
2744 "#636363", "#969696", "#bdbdbd", "#d9d9d9" |
|
2745 ]; |
|
2746 d3.scale.quantile = function() { |
|
2747 return d3_scale_quantile([], []); |
|
2748 }; |
|
2749 |
|
2750 function d3_scale_quantile(domain, range) { |
|
2751 var thresholds; |
|
2752 |
|
2753 function rescale() { |
|
2754 var k = 0, |
|
2755 n = domain.length, |
|
2756 q = range.length; |
|
2757 thresholds = []; |
|
2758 while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q); |
|
2759 return scale; |
|
2760 } |
|
2761 |
|
2762 function scale(x) { |
|
2763 if (isNaN(x = +x)) return NaN; |
|
2764 return range[d3.bisect(thresholds, x)]; |
|
2765 } |
|
2766 |
|
2767 scale.domain = function(x) { |
|
2768 if (!arguments.length) return domain; |
|
2769 domain = x.filter(function(d) { return !isNaN(d); }).sort(d3.ascending); |
|
2770 return rescale(); |
|
2771 }; |
|
2772 |
|
2773 scale.range = function(x) { |
|
2774 if (!arguments.length) return range; |
|
2775 range = x; |
|
2776 return rescale(); |
|
2777 }; |
|
2778 |
|
2779 scale.quantiles = function() { |
|
2780 return thresholds; |
|
2781 }; |
|
2782 |
|
2783 scale.copy = function() { |
|
2784 return d3_scale_quantile(domain, range); // copy on write! |
|
2785 }; |
|
2786 |
|
2787 return rescale(); |
|
2788 }; |
|
2789 d3.scale.quantize = function() { |
|
2790 return d3_scale_quantize(0, 1, [0, 1]); |
|
2791 }; |
|
2792 |
|
2793 function d3_scale_quantize(x0, x1, range) { |
|
2794 var kx, i; |
|
2795 |
|
2796 function scale(x) { |
|
2797 return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))]; |
|
2798 } |
|
2799 |
|
2800 function rescale() { |
|
2801 kx = range.length / (x1 - x0); |
|
2802 i = range.length - 1; |
|
2803 return scale; |
|
2804 } |
|
2805 |
|
2806 scale.domain = function(x) { |
|
2807 if (!arguments.length) return [x0, x1]; |
|
2808 x0 = +x[0]; |
|
2809 x1 = +x[x.length - 1]; |
|
2810 return rescale(); |
|
2811 }; |
|
2812 |
|
2813 scale.range = function(x) { |
|
2814 if (!arguments.length) return range; |
|
2815 range = x; |
|
2816 return rescale(); |
|
2817 }; |
|
2818 |
|
2819 scale.copy = function() { |
|
2820 return d3_scale_quantize(x0, x1, range); // copy on write |
|
2821 }; |
|
2822 |
|
2823 return rescale(); |
|
2824 }; |
|
2825 d3.svg = {}; |
|
2826 d3.svg.arc = function() { |
|
2827 var innerRadius = d3_svg_arcInnerRadius, |
|
2828 outerRadius = d3_svg_arcOuterRadius, |
|
2829 startAngle = d3_svg_arcStartAngle, |
|
2830 endAngle = d3_svg_arcEndAngle; |
|
2831 |
|
2832 function arc() { |
|
2833 var r0 = innerRadius.apply(this, arguments), |
|
2834 r1 = outerRadius.apply(this, arguments), |
|
2835 a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset, |
|
2836 a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset, |
|
2837 da = (a1 < a0 && (da = a0, a0 = a1, a1 = da), a1 - a0), |
|
2838 df = da < Math.PI ? "0" : "1", |
|
2839 c0 = Math.cos(a0), |
|
2840 s0 = Math.sin(a0), |
|
2841 c1 = Math.cos(a1), |
|
2842 s1 = Math.sin(a1); |
|
2843 return da >= d3_svg_arcMax |
|
2844 ? (r0 |
|
2845 ? "M0," + r1 |
|
2846 + "A" + r1 + "," + r1 + " 0 1,1 0," + (-r1) |
|
2847 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 |
|
2848 + "M0," + r0 |
|
2849 + "A" + r0 + "," + r0 + " 0 1,0 0," + (-r0) |
|
2850 + "A" + r0 + "," + r0 + " 0 1,0 0," + r0 |
|
2851 + "Z" |
|
2852 : "M0," + r1 |
|
2853 + "A" + r1 + "," + r1 + " 0 1,1 0," + (-r1) |
|
2854 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 |
|
2855 + "Z") |
|
2856 : (r0 |
|
2857 ? "M" + r1 * c0 + "," + r1 * s0 |
|
2858 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 |
|
2859 + "L" + r0 * c1 + "," + r0 * s1 |
|
2860 + "A" + r0 + "," + r0 + " 0 " + df + ",0 " + r0 * c0 + "," + r0 * s0 |
|
2861 + "Z" |
|
2862 : "M" + r1 * c0 + "," + r1 * s0 |
|
2863 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 |
|
2864 + "L0,0" |
|
2865 + "Z"); |
|
2866 } |
|
2867 |
|
2868 arc.innerRadius = function(v) { |
|
2869 if (!arguments.length) return innerRadius; |
|
2870 innerRadius = d3.functor(v); |
|
2871 return arc; |
|
2872 }; |
|
2873 |
|
2874 arc.outerRadius = function(v) { |
|
2875 if (!arguments.length) return outerRadius; |
|
2876 outerRadius = d3.functor(v); |
|
2877 return arc; |
|
2878 }; |
|
2879 |
|
2880 arc.startAngle = function(v) { |
|
2881 if (!arguments.length) return startAngle; |
|
2882 startAngle = d3.functor(v); |
|
2883 return arc; |
|
2884 }; |
|
2885 |
|
2886 arc.endAngle = function(v) { |
|
2887 if (!arguments.length) return endAngle; |
|
2888 endAngle = d3.functor(v); |
|
2889 return arc; |
|
2890 }; |
|
2891 |
|
2892 arc.centroid = function() { |
|
2893 var r = (innerRadius.apply(this, arguments) |
|
2894 + outerRadius.apply(this, arguments)) / 2, |
|
2895 a = (startAngle.apply(this, arguments) |
|
2896 + endAngle.apply(this, arguments)) / 2 + d3_svg_arcOffset; |
|
2897 return [Math.cos(a) * r, Math.sin(a) * r]; |
|
2898 }; |
|
2899 |
|
2900 return arc; |
|
2901 }; |
|
2902 |
|
2903 var d3_svg_arcOffset = -Math.PI / 2, |
|
2904 d3_svg_arcMax = 2 * Math.PI - 1e-6; |
|
2905 |
|
2906 function d3_svg_arcInnerRadius(d) { |
|
2907 return d.innerRadius; |
|
2908 } |
|
2909 |
|
2910 function d3_svg_arcOuterRadius(d) { |
|
2911 return d.outerRadius; |
|
2912 } |
|
2913 |
|
2914 function d3_svg_arcStartAngle(d) { |
|
2915 return d.startAngle; |
|
2916 } |
|
2917 |
|
2918 function d3_svg_arcEndAngle(d) { |
|
2919 return d.endAngle; |
|
2920 } |
|
2921 function d3_svg_line(projection) { |
|
2922 var x = d3_svg_lineX, |
|
2923 y = d3_svg_lineY, |
|
2924 interpolate = "linear", |
|
2925 interpolator = d3_svg_lineInterpolators[interpolate], |
|
2926 tension = .7; |
|
2927 |
|
2928 function line(d) { |
|
2929 return d.length < 1 ? null : "M" + interpolator(projection(d3_svg_linePoints(this, d, x, y)), tension); |
|
2930 } |
|
2931 |
|
2932 line.x = function(v) { |
|
2933 if (!arguments.length) return x; |
|
2934 x = v; |
|
2935 return line; |
|
2936 }; |
|
2937 |
|
2938 line.y = function(v) { |
|
2939 if (!arguments.length) return y; |
|
2940 y = v; |
|
2941 return line; |
|
2942 }; |
|
2943 |
|
2944 line.interpolate = function(v) { |
|
2945 if (!arguments.length) return interpolate; |
|
2946 interpolator = d3_svg_lineInterpolators[interpolate = v]; |
|
2947 return line; |
|
2948 }; |
|
2949 |
|
2950 line.tension = function(v) { |
|
2951 if (!arguments.length) return tension; |
|
2952 tension = v; |
|
2953 return line; |
|
2954 }; |
|
2955 |
|
2956 return line; |
|
2957 } |
|
2958 |
|
2959 d3.svg.line = function() { |
|
2960 return d3_svg_line(Object); |
|
2961 }; |
|
2962 |
|
2963 // Converts the specified array of data into an array of points |
|
2964 // (x-y tuples), by evaluating the specified `x` and `y` functions on each |
|
2965 // data point. The `this` context of the evaluated functions is the specified |
|
2966 // "self" object; each function is passed the current datum and index. |
|
2967 function d3_svg_linePoints(self, d, x, y) { |
|
2968 var points = [], |
|
2969 i = -1, |
|
2970 n = d.length, |
|
2971 fx = typeof x === "function", |
|
2972 fy = typeof y === "function", |
|
2973 value; |
|
2974 if (fx && fy) { |
|
2975 while (++i < n) points.push([ |
|
2976 x.call(self, value = d[i], i), |
|
2977 y.call(self, value, i) |
|
2978 ]); |
|
2979 } else if (fx) { |
|
2980 while (++i < n) points.push([x.call(self, d[i], i), y]); |
|
2981 } else if (fy) { |
|
2982 while (++i < n) points.push([x, y.call(self, d[i], i)]); |
|
2983 } else { |
|
2984 while (++i < n) points.push([x, y]); |
|
2985 } |
|
2986 return points; |
|
2987 } |
|
2988 |
|
2989 // The default `x` property, which references d[0]. |
|
2990 function d3_svg_lineX(d) { |
|
2991 return d[0]; |
|
2992 } |
|
2993 |
|
2994 // The default `y` property, which references d[1]. |
|
2995 function d3_svg_lineY(d) { |
|
2996 return d[1]; |
|
2997 } |
|
2998 |
|
2999 // The various interpolators supported by the `line` class. |
|
3000 var d3_svg_lineInterpolators = { |
|
3001 "linear": d3_svg_lineLinear, |
|
3002 "step-before": d3_svg_lineStepBefore, |
|
3003 "step-after": d3_svg_lineStepAfter, |
|
3004 "basis": d3_svg_lineBasis, |
|
3005 "basis-open": d3_svg_lineBasisOpen, |
|
3006 "basis-closed": d3_svg_lineBasisClosed, |
|
3007 "bundle": d3_svg_lineBundle, |
|
3008 "cardinal": d3_svg_lineCardinal, |
|
3009 "cardinal-open": d3_svg_lineCardinalOpen, |
|
3010 "cardinal-closed": d3_svg_lineCardinalClosed, |
|
3011 "monotone": d3_svg_lineMonotone |
|
3012 }; |
|
3013 |
|
3014 // Linear interpolation; generates "L" commands. |
|
3015 function d3_svg_lineLinear(points) { |
|
3016 var i = 0, |
|
3017 n = points.length, |
|
3018 p = points[0], |
|
3019 path = [p[0], ",", p[1]]; |
|
3020 while (++i < n) path.push("L", (p = points[i])[0], ",", p[1]); |
|
3021 return path.join(""); |
|
3022 } |
|
3023 |
|
3024 // Step interpolation; generates "H" and "V" commands. |
|
3025 function d3_svg_lineStepBefore(points) { |
|
3026 var i = 0, |
|
3027 n = points.length, |
|
3028 p = points[0], |
|
3029 path = [p[0], ",", p[1]]; |
|
3030 while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]); |
|
3031 return path.join(""); |
|
3032 } |
|
3033 |
|
3034 // Step interpolation; generates "H" and "V" commands. |
|
3035 function d3_svg_lineStepAfter(points) { |
|
3036 var i = 0, |
|
3037 n = points.length, |
|
3038 p = points[0], |
|
3039 path = [p[0], ",", p[1]]; |
|
3040 while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]); |
|
3041 return path.join(""); |
|
3042 } |
|
3043 |
|
3044 // Open cardinal spline interpolation; generates "C" commands. |
|
3045 function d3_svg_lineCardinalOpen(points, tension) { |
|
3046 return points.length < 4 |
|
3047 ? d3_svg_lineLinear(points) |
|
3048 : points[1] + d3_svg_lineHermite(points.slice(1, points.length - 1), |
|
3049 d3_svg_lineCardinalTangents(points, tension)); |
|
3050 } |
|
3051 |
|
3052 // Closed cardinal spline interpolation; generates "C" commands. |
|
3053 function d3_svg_lineCardinalClosed(points, tension) { |
|
3054 return points.length < 3 |
|
3055 ? d3_svg_lineLinear(points) |
|
3056 : points[0] + d3_svg_lineHermite((points.push(points[0]), points), |
|
3057 d3_svg_lineCardinalTangents([points[points.length - 2]] |
|
3058 .concat(points, [points[1]]), tension)); |
|
3059 } |
|
3060 |
|
3061 // Cardinal spline interpolation; generates "C" commands. |
|
3062 function d3_svg_lineCardinal(points, tension, closed) { |
|
3063 return points.length < 3 |
|
3064 ? d3_svg_lineLinear(points) |
|
3065 : points[0] + d3_svg_lineHermite(points, |
|
3066 d3_svg_lineCardinalTangents(points, tension)); |
|
3067 } |
|
3068 |
|
3069 // Hermite spline construction; generates "C" commands. |
|
3070 function d3_svg_lineHermite(points, tangents) { |
|
3071 if (tangents.length < 1 |
|
3072 || (points.length != tangents.length |
|
3073 && points.length != tangents.length + 2)) { |
|
3074 return d3_svg_lineLinear(points); |
|
3075 } |
|
3076 |
|
3077 var quad = points.length != tangents.length, |
|
3078 path = "", |
|
3079 p0 = points[0], |
|
3080 p = points[1], |
|
3081 t0 = tangents[0], |
|
3082 t = t0, |
|
3083 pi = 1; |
|
3084 |
|
3085 if (quad) { |
|
3086 path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) |
|
3087 + "," + p[0] + "," + p[1]; |
|
3088 p0 = points[1]; |
|
3089 pi = 2; |
|
3090 } |
|
3091 |
|
3092 if (tangents.length > 1) { |
|
3093 t = tangents[1]; |
|
3094 p = points[pi]; |
|
3095 pi++; |
|
3096 path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) |
|
3097 + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) |
|
3098 + "," + p[0] + "," + p[1]; |
|
3099 for (var i = 2; i < tangents.length; i++, pi++) { |
|
3100 p = points[pi]; |
|
3101 t = tangents[i]; |
|
3102 path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) |
|
3103 + "," + p[0] + "," + p[1]; |
|
3104 } |
|
3105 } |
|
3106 |
|
3107 if (quad) { |
|
3108 var lp = points[pi]; |
|
3109 path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) |
|
3110 + "," + lp[0] + "," + lp[1]; |
|
3111 } |
|
3112 |
|
3113 return path; |
|
3114 } |
|
3115 |
|
3116 // Generates tangents for a cardinal spline. |
|
3117 function d3_svg_lineCardinalTangents(points, tension) { |
|
3118 var tangents = [], |
|
3119 a = (1 - tension) / 2, |
|
3120 p0, |
|
3121 p1 = points[0], |
|
3122 p2 = points[1], |
|
3123 i = 1, |
|
3124 n = points.length; |
|
3125 while (++i < n) { |
|
3126 p0 = p1; |
|
3127 p1 = p2; |
|
3128 p2 = points[i]; |
|
3129 tangents.push([a * (p2[0] - p0[0]), a * (p2[1] - p0[1])]); |
|
3130 } |
|
3131 return tangents; |
|
3132 } |
|
3133 |
|
3134 // B-spline interpolation; generates "C" commands. |
|
3135 function d3_svg_lineBasis(points) { |
|
3136 if (points.length < 3) return d3_svg_lineLinear(points); |
|
3137 var i = 1, |
|
3138 n = points.length, |
|
3139 pi = points[0], |
|
3140 x0 = pi[0], |
|
3141 y0 = pi[1], |
|
3142 px = [x0, x0, x0, (pi = points[1])[0]], |
|
3143 py = [y0, y0, y0, pi[1]], |
|
3144 path = [x0, ",", y0]; |
|
3145 d3_svg_lineBasisBezier(path, px, py); |
|
3146 while (++i < n) { |
|
3147 pi = points[i]; |
|
3148 px.shift(); px.push(pi[0]); |
|
3149 py.shift(); py.push(pi[1]); |
|
3150 d3_svg_lineBasisBezier(path, px, py); |
|
3151 } |
|
3152 i = -1; |
|
3153 while (++i < 2) { |
|
3154 px.shift(); px.push(pi[0]); |
|
3155 py.shift(); py.push(pi[1]); |
|
3156 d3_svg_lineBasisBezier(path, px, py); |
|
3157 } |
|
3158 return path.join(""); |
|
3159 } |
|
3160 |
|
3161 // Open B-spline interpolation; generates "C" commands. |
|
3162 function d3_svg_lineBasisOpen(points) { |
|
3163 if (points.length < 4) return d3_svg_lineLinear(points); |
|
3164 var path = [], |
|
3165 i = -1, |
|
3166 n = points.length, |
|
3167 pi, |
|
3168 px = [0], |
|
3169 py = [0]; |
|
3170 while (++i < 3) { |
|
3171 pi = points[i]; |
|
3172 px.push(pi[0]); |
|
3173 py.push(pi[1]); |
|
3174 } |
|
3175 path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) |
|
3176 + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py)); |
|
3177 --i; while (++i < n) { |
|
3178 pi = points[i]; |
|
3179 px.shift(); px.push(pi[0]); |
|
3180 py.shift(); py.push(pi[1]); |
|
3181 d3_svg_lineBasisBezier(path, px, py); |
|
3182 } |
|
3183 return path.join(""); |
|
3184 } |
|
3185 |
|
3186 // Closed B-spline interpolation; generates "C" commands. |
|
3187 function d3_svg_lineBasisClosed(points) { |
|
3188 var path, |
|
3189 i = -1, |
|
3190 n = points.length, |
|
3191 m = n + 4, |
|
3192 pi, |
|
3193 px = [], |
|
3194 py = []; |
|
3195 while (++i < 4) { |
|
3196 pi = points[i % n]; |
|
3197 px.push(pi[0]); |
|
3198 py.push(pi[1]); |
|
3199 } |
|
3200 path = [ |
|
3201 d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", |
|
3202 d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) |
|
3203 ]; |
|
3204 --i; while (++i < m) { |
|
3205 pi = points[i % n]; |
|
3206 px.shift(); px.push(pi[0]); |
|
3207 py.shift(); py.push(pi[1]); |
|
3208 d3_svg_lineBasisBezier(path, px, py); |
|
3209 } |
|
3210 return path.join(""); |
|
3211 } |
|
3212 |
|
3213 function d3_svg_lineBundle(points, tension) { |
|
3214 var n = points.length - 1, |
|
3215 x0 = points[0][0], |
|
3216 y0 = points[0][1], |
|
3217 dx = points[n][0] - x0, |
|
3218 dy = points[n][1] - y0, |
|
3219 i = -1, |
|
3220 p, |
|
3221 t; |
|
3222 while (++i <= n) { |
|
3223 p = points[i]; |
|
3224 t = i / n; |
|
3225 p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx); |
|
3226 p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy); |
|
3227 } |
|
3228 return d3_svg_lineBasis(points); |
|
3229 } |
|
3230 |
|
3231 // Returns the dot product of the given four-element vectors. |
|
3232 function d3_svg_lineDot4(a, b) { |
|
3233 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; |
|
3234 } |
|
3235 |
|
3236 // Matrix to transform basis (b-spline) control points to bezier |
|
3237 // control points. Derived from FvD 11.2.8. |
|
3238 var d3_svg_lineBasisBezier1 = [0, 2/3, 1/3, 0], |
|
3239 d3_svg_lineBasisBezier2 = [0, 1/3, 2/3, 0], |
|
3240 d3_svg_lineBasisBezier3 = [0, 1/6, 2/3, 1/6]; |
|
3241 |
|
3242 // Pushes a "C" Bézier curve onto the specified path array, given the |
|
3243 // two specified four-element arrays which define the control points. |
|
3244 function d3_svg_lineBasisBezier(path, x, y) { |
|
3245 path.push( |
|
3246 "C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), |
|
3247 ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), |
|
3248 ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), |
|
3249 ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), |
|
3250 ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), |
|
3251 ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y)); |
|
3252 } |
|
3253 |
|
3254 // Computes the slope from points p0 to p1. |
|
3255 function d3_svg_lineSlope(p0, p1) { |
|
3256 return (p1[1] - p0[1]) / (p1[0] - p0[0]); |
|
3257 } |
|
3258 |
|
3259 // Compute three-point differences for the given points. |
|
3260 // http://en.wikipedia.org/wiki/Cubic_Hermite_spline#Finite_difference |
|
3261 function d3_svg_lineFiniteDifferences(points) { |
|
3262 var i = 0, |
|
3263 j = points.length - 1, |
|
3264 m = [], |
|
3265 p0 = points[0], |
|
3266 p1 = points[1], |
|
3267 d = m[0] = d3_svg_lineSlope(p0, p1); |
|
3268 while (++i < j) { |
|
3269 m[i] = d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1])); |
|
3270 } |
|
3271 m[i] = d; |
|
3272 return m; |
|
3273 } |
|
3274 |
|
3275 // Interpolates the given points using Fritsch-Carlson Monotone cubic Hermite |
|
3276 // interpolation. Returns an array of tangent vectors. For details, see |
|
3277 // http://en.wikipedia.org/wiki/Monotone_cubic_interpolation |
|
3278 function d3_svg_lineMonotoneTangents(points) { |
|
3279 var tangents = [], |
|
3280 d, |
|
3281 a, |
|
3282 b, |
|
3283 s, |
|
3284 m = d3_svg_lineFiniteDifferences(points), |
|
3285 i = -1, |
|
3286 j = points.length - 1; |
|
3287 |
|
3288 // The first two steps are done by computing finite-differences: |
|
3289 // 1. Compute the slopes of the secant lines between successive points. |
|
3290 // 2. Initialize the tangents at every point as the average of the secants. |
|
3291 |
|
3292 // Then, for each segment… |
|
3293 while (++i < j) { |
|
3294 d = d3_svg_lineSlope(points[i], points[i + 1]); |
|
3295 |
|
3296 // 3. If two successive yk = y{k + 1} are equal (i.e., d is zero), then set |
|
3297 // mk = m{k + 1} = 0 as the spline connecting these points must be flat to |
|
3298 // preserve monotonicity. Ignore step 4 and 5 for those k. |
|
3299 |
|
3300 if (Math.abs(d) < 1e-6) { |
|
3301 m[i] = m[i + 1] = 0; |
|
3302 } else { |
|
3303 // 4. Let ak = mk / dk and bk = m{k + 1} / dk. |
|
3304 a = m[i] / d; |
|
3305 b = m[i + 1] / d; |
|
3306 |
|
3307 // 5. Prevent overshoot and ensure monotonicity by restricting the |
|
3308 // magnitude of vector <ak, bk> to a circle of radius 3. |
|
3309 s = a * a + b * b; |
|
3310 if (s > 9) { |
|
3311 s = d * 3 / Math.sqrt(s); |
|
3312 m[i] = s * a; |
|
3313 m[i + 1] = s * b; |
|
3314 } |
|
3315 } |
|
3316 } |
|
3317 |
|
3318 // Compute the normalized tangent vector from the slopes. Note that if x is |
|
3319 // not monotonic, it's possible that the slope will be infinite, so we |
|
3320 // protect |
|
3321 // against NaN by setting the coordinate to zero. |
|
3322 i = -1; while (++i <= j) { |
|
3323 s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) |
|
3324 / (6 * (1 + m[i] * m[i])); |
|
3325 tangents.push([s || 0, m[i] * s || 0]); |
|
3326 } |
|
3327 |
|
3328 return tangents; |
|
3329 } |
|
3330 |
|
3331 function d3_svg_lineMonotone(points) { |
|
3332 return points.length < 3 |
|
3333 ? d3_svg_lineLinear(points) |
|
3334 : points[0] + |
|
3335 d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points)); |
|
3336 } |
|
3337 d3.svg.line.radial = function() { |
|
3338 var line = d3_svg_line(d3_svg_lineRadial); |
|
3339 line.radius = line.x, delete line.x; |
|
3340 line.angle = line.y, delete line.y; |
|
3341 return line; |
|
3342 }; |
|
3343 |
|
3344 function d3_svg_lineRadial(points) { |
|
3345 var point, |
|
3346 i = -1, |
|
3347 n = points.length, |
|
3348 r, |
|
3349 a; |
|
3350 while (++i < n) { |
|
3351 point = points[i]; |
|
3352 r = point[0]; |
|
3353 a = point[1] + d3_svg_arcOffset; |
|
3354 point[0] = r * Math.cos(a); |
|
3355 point[1] = r * Math.sin(a); |
|
3356 } |
|
3357 return points; |
|
3358 } |
|
3359 function d3_svg_area(projection) { |
|
3360 var x0 = d3_svg_lineX, |
|
3361 x1 = d3_svg_lineX, |
|
3362 y0 = 0, |
|
3363 y1 = d3_svg_lineY, |
|
3364 interpolate, |
|
3365 i0, |
|
3366 i1, |
|
3367 tension = .7; |
|
3368 |
|
3369 function area(d) { |
|
3370 if (d.length < 1) return null; |
|
3371 var points0 = d3_svg_linePoints(this, d, x0, y0), |
|
3372 points1 = d3_svg_linePoints(this, d, x0 === x1 ? d3_svg_areaX(points0) : x1, y0 === y1 ? d3_svg_areaY(points0) : y1); |
|
3373 return "M" + i0(projection(points1), tension) |
|
3374 + "L" + i1(projection(points0.reverse()), tension) |
|
3375 + "Z"; |
|
3376 } |
|
3377 |
|
3378 area.x = function(x) { |
|
3379 if (!arguments.length) return x1; |
|
3380 x0 = x1 = x; |
|
3381 return area; |
|
3382 }; |
|
3383 |
|
3384 area.x0 = function(x) { |
|
3385 if (!arguments.length) return x0; |
|
3386 x0 = x; |
|
3387 return area; |
|
3388 }; |
|
3389 |
|
3390 area.x1 = function(x) { |
|
3391 if (!arguments.length) return x1; |
|
3392 x1 = x; |
|
3393 return area; |
|
3394 }; |
|
3395 |
|
3396 area.y = function(y) { |
|
3397 if (!arguments.length) return y1; |
|
3398 y0 = y1 = y; |
|
3399 return area; |
|
3400 }; |
|
3401 |
|
3402 area.y0 = function(y) { |
|
3403 if (!arguments.length) return y0; |
|
3404 y0 = y; |
|
3405 return area; |
|
3406 }; |
|
3407 |
|
3408 area.y1 = function(y) { |
|
3409 if (!arguments.length) return y1; |
|
3410 y1 = y; |
|
3411 return area; |
|
3412 }; |
|
3413 |
|
3414 area.interpolate = function(x) { |
|
3415 if (!arguments.length) return interpolate; |
|
3416 i0 = d3_svg_lineInterpolators[interpolate = x]; |
|
3417 i1 = i0.reverse || i0; |
|
3418 return area; |
|
3419 }; |
|
3420 |
|
3421 area.tension = function(x) { |
|
3422 if (!arguments.length) return tension; |
|
3423 tension = x; |
|
3424 return area; |
|
3425 }; |
|
3426 |
|
3427 return area.interpolate("linear"); |
|
3428 } |
|
3429 |
|
3430 d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter; |
|
3431 d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore; |
|
3432 |
|
3433 d3.svg.area = function() { |
|
3434 return d3_svg_area(Object); |
|
3435 }; |
|
3436 |
|
3437 function d3_svg_areaX(points) { |
|
3438 return function(d, i) { |
|
3439 return points[i][0]; |
|
3440 }; |
|
3441 } |
|
3442 |
|
3443 function d3_svg_areaY(points) { |
|
3444 return function(d, i) { |
|
3445 return points[i][1]; |
|
3446 }; |
|
3447 } |
|
3448 d3.svg.area.radial = function() { |
|
3449 var area = d3_svg_area(d3_svg_lineRadial); |
|
3450 area.radius = area.x, delete area.x; |
|
3451 area.innerRadius = area.x0, delete area.x0; |
|
3452 area.outerRadius = area.x1, delete area.x1; |
|
3453 area.angle = area.y, delete area.y; |
|
3454 area.startAngle = area.y0, delete area.y0; |
|
3455 area.endAngle = area.y1, delete area.y1; |
|
3456 return area; |
|
3457 }; |
|
3458 d3.svg.chord = function() { |
|
3459 var source = d3_svg_chordSource, |
|
3460 target = d3_svg_chordTarget, |
|
3461 radius = d3_svg_chordRadius, |
|
3462 startAngle = d3_svg_arcStartAngle, |
|
3463 endAngle = d3_svg_arcEndAngle; |
|
3464 |
|
3465 // TODO Allow control point to be customized. |
|
3466 |
|
3467 function chord(d, i) { |
|
3468 var s = subgroup(this, source, d, i), |
|
3469 t = subgroup(this, target, d, i); |
|
3470 return "M" + s.p0 |
|
3471 + arc(s.r, s.p1) + (equals(s, t) |
|
3472 ? curve(s.r, s.p1, s.r, s.p0) |
|
3473 : curve(s.r, s.p1, t.r, t.p0) |
|
3474 + arc(t.r, t.p1) |
|
3475 + curve(t.r, t.p1, s.r, s.p0)) |
|
3476 + "Z"; |
|
3477 } |
|
3478 |
|
3479 function subgroup(self, f, d, i) { |
|
3480 var subgroup = f.call(self, d, i), |
|
3481 r = radius.call(self, subgroup, i), |
|
3482 a0 = startAngle.call(self, subgroup, i) + d3_svg_arcOffset, |
|
3483 a1 = endAngle.call(self, subgroup, i) + d3_svg_arcOffset; |
|
3484 return { |
|
3485 r: r, |
|
3486 a0: a0, |
|
3487 a1: a1, |
|
3488 p0: [r * Math.cos(a0), r * Math.sin(a0)], |
|
3489 p1: [r * Math.cos(a1), r * Math.sin(a1)] |
|
3490 }; |
|
3491 } |
|
3492 |
|
3493 function equals(a, b) { |
|
3494 return a.a0 == b.a0 && a.a1 == b.a1; |
|
3495 } |
|
3496 |
|
3497 function arc(r, p) { |
|
3498 return "A" + r + "," + r + " 0 0,1 " + p; |
|
3499 } |
|
3500 |
|
3501 function curve(r0, p0, r1, p1) { |
|
3502 return "Q 0,0 " + p1; |
|
3503 } |
|
3504 |
|
3505 chord.radius = function(v) { |
|
3506 if (!arguments.length) return radius; |
|
3507 radius = d3.functor(v); |
|
3508 return chord; |
|
3509 }; |
|
3510 |
|
3511 chord.source = function(v) { |
|
3512 if (!arguments.length) return source; |
|
3513 source = d3.functor(v); |
|
3514 return chord; |
|
3515 }; |
|
3516 |
|
3517 chord.target = function(v) { |
|
3518 if (!arguments.length) return target; |
|
3519 target = d3.functor(v); |
|
3520 return chord; |
|
3521 }; |
|
3522 |
|
3523 chord.startAngle = function(v) { |
|
3524 if (!arguments.length) return startAngle; |
|
3525 startAngle = d3.functor(v); |
|
3526 return chord; |
|
3527 }; |
|
3528 |
|
3529 chord.endAngle = function(v) { |
|
3530 if (!arguments.length) return endAngle; |
|
3531 endAngle = d3.functor(v); |
|
3532 return chord; |
|
3533 }; |
|
3534 |
|
3535 return chord; |
|
3536 }; |
|
3537 |
|
3538 function d3_svg_chordSource(d) { |
|
3539 return d.source; |
|
3540 } |
|
3541 |
|
3542 function d3_svg_chordTarget(d) { |
|
3543 return d.target; |
|
3544 } |
|
3545 |
|
3546 function d3_svg_chordRadius(d) { |
|
3547 return d.radius; |
|
3548 } |
|
3549 |
|
3550 function d3_svg_chordStartAngle(d) { |
|
3551 return d.startAngle; |
|
3552 } |
|
3553 |
|
3554 function d3_svg_chordEndAngle(d) { |
|
3555 return d.endAngle; |
|
3556 } |
|
3557 d3.svg.diagonal = function() { |
|
3558 var source = d3_svg_chordSource, |
|
3559 target = d3_svg_chordTarget, |
|
3560 projection = d3_svg_diagonalProjection; |
|
3561 |
|
3562 function diagonal(d, i) { |
|
3563 var p0 = source.call(this, d, i), |
|
3564 p3 = target.call(this, d, i), |
|
3565 m = (p0.y + p3.y) / 2, |
|
3566 p = [p0, {x: p0.x, y: m}, {x: p3.x, y: m}, p3]; |
|
3567 p = p.map(projection); |
|
3568 return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3]; |
|
3569 } |
|
3570 |
|
3571 diagonal.source = function(x) { |
|
3572 if (!arguments.length) return source; |
|
3573 source = d3.functor(x); |
|
3574 return diagonal; |
|
3575 }; |
|
3576 |
|
3577 diagonal.target = function(x) { |
|
3578 if (!arguments.length) return target; |
|
3579 target = d3.functor(x); |
|
3580 return diagonal; |
|
3581 }; |
|
3582 |
|
3583 diagonal.projection = function(x) { |
|
3584 if (!arguments.length) return projection; |
|
3585 projection = x; |
|
3586 return diagonal; |
|
3587 }; |
|
3588 |
|
3589 return diagonal; |
|
3590 }; |
|
3591 |
|
3592 function d3_svg_diagonalProjection(d) { |
|
3593 return [d.x, d.y]; |
|
3594 } |
|
3595 d3.svg.diagonal.radial = function() { |
|
3596 var diagonal = d3.svg.diagonal(), |
|
3597 projection = d3_svg_diagonalProjection, |
|
3598 projection_ = diagonal.projection; |
|
3599 |
|
3600 diagonal.projection = function(x) { |
|
3601 return arguments.length |
|
3602 ? projection_(d3_svg_diagonalRadialProjection(projection = x)) |
|
3603 : projection; |
|
3604 }; |
|
3605 |
|
3606 return diagonal; |
|
3607 }; |
|
3608 |
|
3609 function d3_svg_diagonalRadialProjection(projection) { |
|
3610 return function() { |
|
3611 var d = projection.apply(this, arguments), |
|
3612 r = d[0], |
|
3613 a = d[1] + d3_svg_arcOffset; |
|
3614 return [r * Math.cos(a), r * Math.sin(a)]; |
|
3615 }; |
|
3616 } |
|
3617 d3.svg.mouse = function(container) { |
|
3618 return d3_svg_mousePoint(container, d3.event); |
|
3619 }; |
|
3620 |
|
3621 // https://bugs.webkit.org/show_bug.cgi?id=44083 |
|
3622 var d3_mouse_bug44083 = /WebKit/.test(navigator.userAgent) ? -1 : 0; |
|
3623 |
|
3624 function d3_svg_mousePoint(container, e) { |
|
3625 var point = (container.ownerSVGElement || container).createSVGPoint(); |
|
3626 if ((d3_mouse_bug44083 < 0) && (window.scrollX || window.scrollY)) { |
|
3627 var svg = d3.select(document.body) |
|
3628 .append("svg:svg") |
|
3629 .style("position", "absolute") |
|
3630 .style("top", 0) |
|
3631 .style("left", 0); |
|
3632 var ctm = svg[0][0].getScreenCTM(); |
|
3633 d3_mouse_bug44083 = !(ctm.f || ctm.e); |
|
3634 svg.remove(); |
|
3635 } |
|
3636 if (d3_mouse_bug44083) { |
|
3637 point.x = e.pageX; |
|
3638 point.y = e.pageY; |
|
3639 } else { |
|
3640 point.x = e.clientX; |
|
3641 point.y = e.clientY; |
|
3642 } |
|
3643 point = point.matrixTransform(container.getScreenCTM().inverse()); |
|
3644 return [point.x, point.y]; |
|
3645 }; |
|
3646 d3.svg.touches = function(container, touches) { |
|
3647 if (arguments.length < 2) touches = d3.event.touches; |
|
3648 |
|
3649 return touches ? d3_array(touches).map(function(touch) { |
|
3650 var point = d3_svg_mousePoint(container, touch); |
|
3651 point.identifier = touch.identifier; |
|
3652 return point; |
|
3653 }) : []; |
|
3654 }; |
|
3655 d3.svg.symbol = function() { |
|
3656 var type = d3_svg_symbolType, |
|
3657 size = d3_svg_symbolSize; |
|
3658 |
|
3659 function symbol(d, i) { |
|
3660 return (d3_svg_symbols[type.call(this, d, i)] |
|
3661 || d3_svg_symbols.circle) |
|
3662 (size.call(this, d, i)); |
|
3663 } |
|
3664 |
|
3665 symbol.type = function(x) { |
|
3666 if (!arguments.length) return type; |
|
3667 type = d3.functor(x); |
|
3668 return symbol; |
|
3669 }; |
|
3670 |
|
3671 // size of symbol in square pixels |
|
3672 symbol.size = function(x) { |
|
3673 if (!arguments.length) return size; |
|
3674 size = d3.functor(x); |
|
3675 return symbol; |
|
3676 }; |
|
3677 |
|
3678 return symbol; |
|
3679 }; |
|
3680 |
|
3681 function d3_svg_symbolSize() { |
|
3682 return 64; |
|
3683 } |
|
3684 |
|
3685 function d3_svg_symbolType() { |
|
3686 return "circle"; |
|
3687 } |
|
3688 |
|
3689 // TODO cross-diagonal? |
|
3690 var d3_svg_symbols = { |
|
3691 "circle": function(size) { |
|
3692 var r = Math.sqrt(size / Math.PI); |
|
3693 return "M0," + r |
|
3694 + "A" + r + "," + r + " 0 1,1 0," + (-r) |
|
3695 + "A" + r + "," + r + " 0 1,1 0," + r |
|
3696 + "Z"; |
|
3697 }, |
|
3698 "cross": function(size) { |
|
3699 var r = Math.sqrt(size / 5) / 2; |
|
3700 return "M" + -3 * r + "," + -r |
|
3701 + "H" + -r |
|
3702 + "V" + -3 * r |
|
3703 + "H" + r |
|
3704 + "V" + -r |
|
3705 + "H" + 3 * r |
|
3706 + "V" + r |
|
3707 + "H" + r |
|
3708 + "V" + 3 * r |
|
3709 + "H" + -r |
|
3710 + "V" + r |
|
3711 + "H" + -3 * r |
|
3712 + "Z"; |
|
3713 }, |
|
3714 "diamond": function(size) { |
|
3715 var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), |
|
3716 rx = ry * d3_svg_symbolTan30; |
|
3717 return "M0," + -ry |
|
3718 + "L" + rx + ",0" |
|
3719 + " 0," + ry |
|
3720 + " " + -rx + ",0" |
|
3721 + "Z"; |
|
3722 }, |
|
3723 "square": function(size) { |
|
3724 var r = Math.sqrt(size) / 2; |
|
3725 return "M" + -r + "," + -r |
|
3726 + "L" + r + "," + -r |
|
3727 + " " + r + "," + r |
|
3728 + " " + -r + "," + r |
|
3729 + "Z"; |
|
3730 }, |
|
3731 "triangle-down": function(size) { |
|
3732 var rx = Math.sqrt(size / d3_svg_symbolSqrt3), |
|
3733 ry = rx * d3_svg_symbolSqrt3 / 2; |
|
3734 return "M0," + ry |
|
3735 + "L" + rx +"," + -ry |
|
3736 + " " + -rx + "," + -ry |
|
3737 + "Z"; |
|
3738 }, |
|
3739 "triangle-up": function(size) { |
|
3740 var rx = Math.sqrt(size / d3_svg_symbolSqrt3), |
|
3741 ry = rx * d3_svg_symbolSqrt3 / 2; |
|
3742 return "M0," + -ry |
|
3743 + "L" + rx +"," + ry |
|
3744 + " " + -rx + "," + ry |
|
3745 + "Z"; |
|
3746 } |
|
3747 }; |
|
3748 |
|
3749 d3.svg.symbolTypes = d3.keys(d3_svg_symbols); |
|
3750 |
|
3751 var d3_svg_symbolSqrt3 = Math.sqrt(3), |
|
3752 d3_svg_symbolTan30 = Math.tan(30 * Math.PI / 180); |
|
3753 d3.svg.axis = function() { |
|
3754 var scale = d3.scale.linear(), |
|
3755 orient = "bottom", |
|
3756 tickMajorSize = 6, |
|
3757 tickMinorSize = 6, |
|
3758 tickEndSize = 6, |
|
3759 tickPadding = 3, |
|
3760 tickArguments_ = [10], |
|
3761 tickFormat_, |
|
3762 tickSubdivide = 0; |
|
3763 |
|
3764 function axis(selection) { |
|
3765 selection.each(function(d, i, j) { |
|
3766 var g = d3.select(this); |
|
3767 |
|
3768 // If selection is a transition, create subtransitions. |
|
3769 var transition = selection.delay ? function(o) { |
|
3770 var id = d3_transitionInheritId; |
|
3771 try { |
|
3772 d3_transitionInheritId = selection.id; |
|
3773 return o.transition() |
|
3774 .delay(selection[j][i].delay) |
|
3775 .duration(selection[j][i].duration) |
|
3776 .ease(selection.ease()); |
|
3777 } finally { |
|
3778 d3_transitionInheritId = id; |
|
3779 } |
|
3780 } : Object; |
|
3781 |
|
3782 // Ticks. |
|
3783 var ticks = scale.ticks.apply(scale, tickArguments_), |
|
3784 tickFormat = tickFormat_ == null ? scale.tickFormat.apply(scale, tickArguments_) : tickFormat_; |
|
3785 |
|
3786 // Minor ticks. |
|
3787 var subticks = d3_svg_axisSubdivide(scale, ticks, tickSubdivide), |
|
3788 subtick = g.selectAll(".minor").data(subticks, String), |
|
3789 subtickEnter = subtick.enter().insert("svg:line", "g").attr("class", "tick minor").style("opacity", 1e-6), |
|
3790 subtickExit = transition(subtick.exit()).style("opacity", 1e-6).remove(), |
|
3791 subtickUpdate = transition(subtick).style("opacity", 1); |
|
3792 |
|
3793 // Major ticks. |
|
3794 var tick = g.selectAll("g").data(ticks, String), |
|
3795 tickEnter = tick.enter().insert("svg:g", "path").style("opacity", 1e-6), |
|
3796 tickExit = transition(tick.exit()).style("opacity", 1e-6).remove(), |
|
3797 tickUpdate = transition(tick).style("opacity", 1), |
|
3798 tickTransform; |
|
3799 |
|
3800 // Domain. |
|
3801 var range = d3_scaleExtent(scale.range()), |
|
3802 path = g.selectAll(".domain").data([0]), |
|
3803 pathEnter = path.enter().append("svg:path").attr("class", "domain"), |
|
3804 pathUpdate = transition(path); |
|
3805 |
|
3806 // Stash the new scale and grab the old scale. |
|
3807 var scale0 = this.__chart__ || scale; |
|
3808 this.__chart__ = scale.copy(); |
|
3809 |
|
3810 tickEnter.append("svg:line").attr("class", "tick"); |
|
3811 tickEnter.append("svg:text"); |
|
3812 tickUpdate.select("text").text(tickFormat); |
|
3813 |
|
3814 switch (orient) { |
|
3815 case "bottom": { |
|
3816 tickTransform = d3_svg_axisX; |
|
3817 subtickUpdate.attr("x2", 0).attr("y2", tickMinorSize); |
|
3818 tickUpdate.select("line").attr("x2", 0).attr("y2", tickMajorSize); |
|
3819 tickUpdate.select("text").attr("x", 0).attr("y", Math.max(tickMajorSize, 0) + tickPadding).attr("dy", ".71em").attr("text-anchor", "middle"); |
|
3820 pathUpdate.attr("d", "M" + range[0] + "," + tickEndSize + "V0H" + range[1] + "V" + tickEndSize); |
|
3821 break; |
|
3822 } |
|
3823 case "top": { |
|
3824 tickTransform = d3_svg_axisX; |
|
3825 subtickUpdate.attr("x2", 0).attr("y2", -tickMinorSize); |
|
3826 tickUpdate.select("line").attr("x2", 0).attr("y2", -tickMajorSize); |
|
3827 tickUpdate.select("text").attr("x", 0).attr("y", -(Math.max(tickMajorSize, 0) + tickPadding)).attr("dy", "0em").attr("text-anchor", "middle"); |
|
3828 pathUpdate.attr("d", "M" + range[0] + "," + -tickEndSize + "V0H" + range[1] + "V" + -tickEndSize); |
|
3829 break; |
|
3830 } |
|
3831 case "left": { |
|
3832 tickTransform = d3_svg_axisY; |
|
3833 subtickUpdate.attr("x2", -tickMinorSize).attr("y2", 0); |
|
3834 tickUpdate.select("line").attr("x2", -tickMajorSize).attr("y2", 0); |
|
3835 tickUpdate.select("text").attr("x", -(Math.max(tickMajorSize, 0) + tickPadding)).attr("y", 0).attr("dy", ".32em").attr("text-anchor", "end"); |
|
3836 pathUpdate.attr("d", "M" + -tickEndSize + "," + range[0] + "H0V" + range[1] + "H" + -tickEndSize); |
|
3837 break; |
|
3838 } |
|
3839 case "right": { |
|
3840 tickTransform = d3_svg_axisY; |
|
3841 subtickUpdate.attr("x2", tickMinorSize).attr("y2", 0); |
|
3842 tickUpdate.select("line").attr("x2", tickMajorSize).attr("y2", 0); |
|
3843 tickUpdate.select("text").attr("x", Math.max(tickMajorSize, 0) + tickPadding).attr("y", 0).attr("dy", ".32em").attr("text-anchor", "start"); |
|
3844 pathUpdate.attr("d", "M" + tickEndSize + "," + range[0] + "H0V" + range[1] + "H" + tickEndSize); |
|
3845 break; |
|
3846 } |
|
3847 } |
|
3848 |
|
3849 tickEnter.call(tickTransform, scale0); |
|
3850 tickUpdate.call(tickTransform, scale); |
|
3851 tickExit.call(tickTransform, scale); |
|
3852 |
|
3853 subtickEnter.call(tickTransform, scale0); |
|
3854 subtickUpdate.call(tickTransform, scale); |
|
3855 subtickExit.call(tickTransform, scale); |
|
3856 }); |
|
3857 } |
|
3858 |
|
3859 axis.scale = function(x) { |
|
3860 if (!arguments.length) return scale; |
|
3861 scale = x; |
|
3862 return axis; |
|
3863 }; |
|
3864 |
|
3865 axis.orient = function(x) { |
|
3866 if (!arguments.length) return orient; |
|
3867 orient = x; |
|
3868 return axis; |
|
3869 }; |
|
3870 |
|
3871 axis.ticks = function() { |
|
3872 if (!arguments.length) return tickArguments_; |
|
3873 tickArguments_ = arguments; |
|
3874 return axis; |
|
3875 }; |
|
3876 |
|
3877 axis.tickFormat = function(x) { |
|
3878 if (!arguments.length) return tickFormat_; |
|
3879 tickFormat_ = x; |
|
3880 return axis; |
|
3881 }; |
|
3882 |
|
3883 axis.tickSize = function(x, y, z) { |
|
3884 if (!arguments.length) return tickMajorSize; |
|
3885 var n = arguments.length - 1; |
|
3886 tickMajorSize = +x; |
|
3887 tickMinorSize = n > 1 ? +y : tickMajorSize; |
|
3888 tickEndSize = n > 0 ? +arguments[n] : tickMajorSize; |
|
3889 return axis; |
|
3890 }; |
|
3891 |
|
3892 axis.tickPadding = function(x) { |
|
3893 if (!arguments.length) return tickPadding; |
|
3894 tickPadding = +x; |
|
3895 return axis; |
|
3896 }; |
|
3897 |
|
3898 axis.tickSubdivide = function(x) { |
|
3899 if (!arguments.length) return tickSubdivide; |
|
3900 tickSubdivide = +x; |
|
3901 return axis; |
|
3902 }; |
|
3903 |
|
3904 return axis; |
|
3905 }; |
|
3906 |
|
3907 function d3_svg_axisX(selection, x) { |
|
3908 selection.attr("transform", function(d) { return "translate(" + x(d) + ",0)"; }); |
|
3909 } |
|
3910 |
|
3911 function d3_svg_axisY(selection, y) { |
|
3912 selection.attr("transform", function(d) { return "translate(0," + y(d) + ")"; }); |
|
3913 } |
|
3914 |
|
3915 function d3_svg_axisSubdivide(scale, ticks, m) { |
|
3916 subticks = []; |
|
3917 if (m && ticks.length > 1) { |
|
3918 var extent = d3_scaleExtent(scale.domain()), |
|
3919 subticks, |
|
3920 i = -1, |
|
3921 n = ticks.length, |
|
3922 d = (ticks[1] - ticks[0]) / ++m, |
|
3923 j, |
|
3924 v; |
|
3925 while (++i < n) { |
|
3926 for (j = m; --j > 0;) { |
|
3927 if ((v = +ticks[i] - j * d) >= extent[0]) { |
|
3928 subticks.push(v); |
|
3929 } |
|
3930 } |
|
3931 } |
|
3932 for (--i, j = 0; ++j < m && (v = +ticks[i] + j * d) < extent[1];) { |
|
3933 subticks.push(v); |
|
3934 } |
|
3935 } |
|
3936 return subticks; |
|
3937 } |
|
3938 d3.svg.brush = function() { |
|
3939 var event = d3.dispatch("brushstart", "brush", "brushend"), |
|
3940 x, // x-scale, optional |
|
3941 y, // y-scale, optional |
|
3942 extent = [[0, 0], [0, 0]]; // [x0, y0], [x1, y1] |
|
3943 |
|
3944 function brush(g) { |
|
3945 var resizes = x && y ? ["n", "e", "s", "w", "nw", "ne", "se", "sw"] |
|
3946 : x ? ["e", "w"] |
|
3947 : y ? ["n", "s"] |
|
3948 : []; |
|
3949 |
|
3950 g.each(function() { |
|
3951 var g = d3.select(this).on("mousedown.brush", down), |
|
3952 bg = g.selectAll(".background").data([,]), |
|
3953 fg = g.selectAll(".extent").data([,]), |
|
3954 tz = g.selectAll(".resize").data(resizes, String), |
|
3955 e; |
|
3956 |
|
3957 // An invisible, mouseable area for starting a new brush. |
|
3958 bg.enter().append("svg:rect") |
|
3959 .attr("class", "background") |
|
3960 .style("visibility", "hidden") |
|
3961 .style("pointer-events", "all") |
|
3962 .style("cursor", "crosshair"); |
|
3963 |
|
3964 // The visible brush extent; style this as you like! |
|
3965 fg.enter().append("svg:rect") |
|
3966 .attr("class", "extent") |
|
3967 .style("cursor", "move"); |
|
3968 |
|
3969 // More invisible rects for resizing the extent. |
|
3970 tz.enter().append("svg:rect") |
|
3971 .attr("class", function(d) { return "resize " + d; }) |
|
3972 .attr("width", 6) |
|
3973 .attr("height", 6) |
|
3974 .style("visibility", "hidden") |
|
3975 .style("pointer-events", brush.empty() ? "none" : "all") |
|
3976 .style("cursor", function(d) { return d3_svg_brushCursor[d]; }); |
|
3977 |
|
3978 // Remove any superfluous resizers. |
|
3979 tz.exit().remove(); |
|
3980 |
|
3981 // Initialize the background to fill the defined range. |
|
3982 // If the range isn't defined, you can post-process. |
|
3983 if (x) { |
|
3984 e = d3_scaleExtent(x.range()); |
|
3985 bg.attr("x", e[0]).attr("width", e[1] - e[0]); |
|
3986 d3_svg_brushRedrawX(g, extent); |
|
3987 } |
|
3988 if (y) { |
|
3989 e = d3_scaleExtent(y.range()); |
|
3990 bg.attr("y", e[0]).attr("height", e[1] - e[0]); |
|
3991 d3_svg_brushRedrawY(g, extent); |
|
3992 } |
|
3993 }); |
|
3994 } |
|
3995 |
|
3996 function down() { |
|
3997 var target = d3.select(d3.event.target); |
|
3998 |
|
3999 // Store some global state for the duration of the brush gesture. |
|
4000 d3_svg_brush = brush; |
|
4001 d3_svg_brushTarget = this; |
|
4002 d3_svg_brushExtent = extent; |
|
4003 d3_svg_brushOffset = d3.svg.mouse(d3_svg_brushTarget); |
|
4004 |
|
4005 // If the extent was clicked on, drag rather than brush; |
|
4006 // store the offset between the mouse and extent origin instead. |
|
4007 if (d3_svg_brushDrag = target.classed("extent")) { |
|
4008 d3_svg_brushOffset[0] = extent[0][0] - d3_svg_brushOffset[0]; |
|
4009 d3_svg_brushOffset[1] = extent[0][1] - d3_svg_brushOffset[1]; |
|
4010 } |
|
4011 |
|
4012 // If a resizer was clicked on, record which side is to be resized. |
|
4013 // Also, set the offset to the opposite side. |
|
4014 else if (target.classed("resize")) { |
|
4015 d3_svg_brushResize = d3.event.target.__data__; |
|
4016 d3_svg_brushOffset[0] = extent[+/w$/.test(d3_svg_brushResize)][0]; |
|
4017 d3_svg_brushOffset[1] = extent[+/^n/.test(d3_svg_brushResize)][1]; |
|
4018 } |
|
4019 |
|
4020 // If the ALT key is down when starting a brush, the center is at the mouse. |
|
4021 else if (d3.event.altKey) { |
|
4022 d3_svg_brushCenter = d3_svg_brushOffset.slice(); |
|
4023 } |
|
4024 |
|
4025 // Restrict which dimensions are resized. |
|
4026 d3_svg_brushX = !/^(n|s)$/.test(d3_svg_brushResize) && x; |
|
4027 d3_svg_brushY = !/^(e|w)$/.test(d3_svg_brushResize) && y; |
|
4028 |
|
4029 // Notify listeners. |
|
4030 d3_svg_brushDispatch = dispatcher(this, arguments); |
|
4031 d3_svg_brushDispatch("brushstart"); |
|
4032 d3_svg_brushMove(); |
|
4033 d3_eventCancel(); |
|
4034 } |
|
4035 |
|
4036 function dispatcher(that, argumentz) { |
|
4037 return function(type) { |
|
4038 var e = d3.event; |
|
4039 try { |
|
4040 d3.event = {type: type, target: brush}; |
|
4041 event[type].apply(that, argumentz); |
|
4042 } finally { |
|
4043 d3.event = e; |
|
4044 } |
|
4045 }; |
|
4046 } |
|
4047 |
|
4048 brush.x = function(z) { |
|
4049 if (!arguments.length) return x; |
|
4050 x = z; |
|
4051 return brush; |
|
4052 }; |
|
4053 |
|
4054 brush.y = function(z) { |
|
4055 if (!arguments.length) return y; |
|
4056 y = z; |
|
4057 return brush; |
|
4058 }; |
|
4059 |
|
4060 brush.extent = function(z) { |
|
4061 var x0, x1, y0, y1, t; |
|
4062 |
|
4063 // Invert the pixel extent to data-space. |
|
4064 if (!arguments.length) { |
|
4065 if (x) { |
|
4066 x0 = x.invert(extent[0][0]), x1 = x.invert(extent[1][0]); |
|
4067 if (x1 < x0) t = x0, x0 = x1, x1 = t; |
|
4068 } |
|
4069 if (y) { |
|
4070 y0 = y.invert(extent[0][1]), y1 = y.invert(extent[1][1]); |
|
4071 if (y1 < y0) t = y0, y0 = y1, y1 = t; |
|
4072 } |
|
4073 return x && y ? [[x0, y0], [x1, y1]] : x ? [x0, x1] : y && [y0, y1]; |
|
4074 } |
|
4075 |
|
4076 // Scale the data-space extent to pixels. |
|
4077 if (x) { |
|
4078 x0 = z[0], x1 = z[1]; |
|
4079 if (y) x0 = x0[0], x1 = x1[0]; |
|
4080 x0 = x(x0), x1 = x(x1); |
|
4081 if (x1 < x0) t = x0, x0 = x1, x1 = t; |
|
4082 extent[0][0] = x0, extent[1][0] = x1; |
|
4083 } |
|
4084 if (y) { |
|
4085 y0 = z[0], y1 = z[1]; |
|
4086 if (x) y0 = y0[1], y1 = y1[1]; |
|
4087 y0 = y(y0), y1 = y(y1); |
|
4088 if (y1 < y0) t = y0, y0 = y1, y1 = t; |
|
4089 extent[0][1] = y0, extent[1][1] = y1; |
|
4090 } |
|
4091 |
|
4092 return brush; |
|
4093 }; |
|
4094 |
|
4095 brush.clear = function() { |
|
4096 extent[0][0] = |
|
4097 extent[0][1] = |
|
4098 extent[1][0] = |
|
4099 extent[1][1] = 0; |
|
4100 return brush; |
|
4101 }; |
|
4102 |
|
4103 brush.empty = function() { |
|
4104 return (x && extent[0][0] === extent[1][0]) |
|
4105 || (y && extent[0][1] === extent[1][1]); |
|
4106 }; |
|
4107 |
|
4108 brush.on = function(type, listener) { |
|
4109 event.on(type, listener); |
|
4110 return brush; |
|
4111 }; |
|
4112 |
|
4113 d3.select(window) |
|
4114 .on("mousemove.brush", d3_svg_brushMove) |
|
4115 .on("mouseup.brush", d3_svg_brushUp) |
|
4116 .on("keydown.brush", d3_svg_brushKeydown) |
|
4117 .on("keyup.brush", d3_svg_brushKeyup); |
|
4118 |
|
4119 return brush; |
|
4120 }; |
|
4121 |
|
4122 var d3_svg_brush, |
|
4123 d3_svg_brushDispatch, |
|
4124 d3_svg_brushTarget, |
|
4125 d3_svg_brushX, |
|
4126 d3_svg_brushY, |
|
4127 d3_svg_brushExtent, |
|
4128 d3_svg_brushDrag, |
|
4129 d3_svg_brushResize, |
|
4130 d3_svg_brushCenter, |
|
4131 d3_svg_brushOffset; |
|
4132 |
|
4133 function d3_svg_brushRedrawX(g, extent) { |
|
4134 g.select(".extent").attr("x", extent[0][0]); |
|
4135 g.selectAll(".n,.s,.w,.nw,.sw").attr("x", extent[0][0] - 2); |
|
4136 g.selectAll(".e,.ne,.se").attr("x", extent[1][0] - 3); |
|
4137 g.selectAll(".extent,.n,.s").attr("width", extent[1][0] - extent[0][0]); |
|
4138 } |
|
4139 |
|
4140 function d3_svg_brushRedrawY(g, extent) { |
|
4141 g.select(".extent").attr("y", extent[0][1]); |
|
4142 g.selectAll(".n,.e,.w,.nw,.ne").attr("y", extent[0][1] - 3); |
|
4143 g.selectAll(".s,.se,.sw").attr("y", extent[1][1] - 4); |
|
4144 g.selectAll(".extent,.e,.w").attr("height", extent[1][1] - extent[0][1]); |
|
4145 } |
|
4146 |
|
4147 function d3_svg_brushKeydown() { |
|
4148 if (d3.event.keyCode == 32 && d3_svg_brushTarget && !d3_svg_brushDrag) { |
|
4149 d3_svg_brushCenter = null; |
|
4150 d3_svg_brushOffset[0] -= d3_svg_brushExtent[1][0]; |
|
4151 d3_svg_brushOffset[1] -= d3_svg_brushExtent[1][1]; |
|
4152 d3_svg_brushDrag = 2; |
|
4153 d3_eventCancel(); |
|
4154 } |
|
4155 } |
|
4156 |
|
4157 function d3_svg_brushKeyup() { |
|
4158 if (d3.event.keyCode == 32 && d3_svg_brushDrag == 2) { |
|
4159 d3_svg_brushOffset[0] += d3_svg_brushExtent[1][0]; |
|
4160 d3_svg_brushOffset[1] += d3_svg_brushExtent[1][1]; |
|
4161 d3_svg_brushDrag = 0; |
|
4162 d3_eventCancel(); |
|
4163 } |
|
4164 } |
|
4165 |
|
4166 function d3_svg_brushMove() { |
|
4167 if (d3_svg_brushOffset) { |
|
4168 var mouse = d3.svg.mouse(d3_svg_brushTarget), |
|
4169 g = d3.select(d3_svg_brushTarget); |
|
4170 |
|
4171 if (!d3_svg_brushDrag) { |
|
4172 |
|
4173 // If needed, determine the center from the current extent. |
|
4174 if (d3.event.altKey) { |
|
4175 if (!d3_svg_brushCenter) { |
|
4176 d3_svg_brushCenter = [ |
|
4177 (d3_svg_brushExtent[0][0] + d3_svg_brushExtent[1][0]) / 2, |
|
4178 (d3_svg_brushExtent[0][1] + d3_svg_brushExtent[1][1]) / 2 |
|
4179 ]; |
|
4180 } |
|
4181 |
|
4182 // Update the offset, for when the ALT key is released. |
|
4183 d3_svg_brushOffset[0] = d3_svg_brushExtent[+(mouse[0] < d3_svg_brushCenter[0])][0]; |
|
4184 d3_svg_brushOffset[1] = d3_svg_brushExtent[+(mouse[1] < d3_svg_brushCenter[1])][1]; |
|
4185 } |
|
4186 |
|
4187 // When the ALT key is released, we clear the center. |
|
4188 else d3_svg_brushCenter = null; |
|
4189 } |
|
4190 |
|
4191 // Update the brush extent for each dimension. |
|
4192 if (d3_svg_brushX) { |
|
4193 d3_svg_brushMove1(mouse, d3_svg_brushX, 0); |
|
4194 d3_svg_brushRedrawX(g, d3_svg_brushExtent); |
|
4195 } |
|
4196 if (d3_svg_brushY) { |
|
4197 d3_svg_brushMove1(mouse, d3_svg_brushY, 1); |
|
4198 d3_svg_brushRedrawY(g, d3_svg_brushExtent); |
|
4199 } |
|
4200 |
|
4201 // Notify listeners. |
|
4202 d3_svg_brushDispatch("brush"); |
|
4203 } |
|
4204 } |
|
4205 |
|
4206 function d3_svg_brushMove1(mouse, scale, i) { |
|
4207 var range = d3_scaleExtent(scale.range()), |
|
4208 offset = d3_svg_brushOffset[i], |
|
4209 size = d3_svg_brushExtent[1][i] - d3_svg_brushExtent[0][i], |
|
4210 min, |
|
4211 max; |
|
4212 |
|
4213 // When dragging, reduce the range by the extent size and offset. |
|
4214 if (d3_svg_brushDrag) { |
|
4215 range[0] -= offset; |
|
4216 range[1] -= size + offset; |
|
4217 } |
|
4218 |
|
4219 // Clamp the mouse so that the extent fits within the range extent. |
|
4220 min = Math.max(range[0], Math.min(range[1], mouse[i])); |
|
4221 |
|
4222 // Compute the new extent bounds. |
|
4223 if (d3_svg_brushDrag) { |
|
4224 max = (min += offset) + size; |
|
4225 } else { |
|
4226 |
|
4227 // If the ALT key is pressed, then preserve the center of the extent. |
|
4228 if (d3_svg_brushCenter) offset = Math.max(range[0], Math.min(range[1], 2 * d3_svg_brushCenter[i] - min)); |
|
4229 |
|
4230 // Compute the min and max of the offset and mouse. |
|
4231 if (offset < min) { |
|
4232 max = min; |
|
4233 min = offset; |
|
4234 } else { |
|
4235 max = offset; |
|
4236 } |
|
4237 } |
|
4238 |
|
4239 // Update the stored bounds. |
|
4240 d3_svg_brushExtent[0][i] = min; |
|
4241 d3_svg_brushExtent[1][i] = max; |
|
4242 } |
|
4243 |
|
4244 function d3_svg_brushUp() { |
|
4245 if (d3_svg_brushOffset) { |
|
4246 d3_svg_brushMove(); |
|
4247 d3.select(d3_svg_brushTarget).selectAll(".resize").style("pointer-events", d3_svg_brush.empty() ? "none" : "all"); |
|
4248 d3_svg_brushDispatch("brushend"); |
|
4249 d3_svg_brush = |
|
4250 d3_svg_brushDispatch = |
|
4251 d3_svg_brushTarget = |
|
4252 d3_svg_brushX = |
|
4253 d3_svg_brushY = |
|
4254 d3_svg_brushExtent = |
|
4255 d3_svg_brushDrag = |
|
4256 d3_svg_brushResize = |
|
4257 d3_svg_brushCenter = |
|
4258 d3_svg_brushOffset = null; |
|
4259 d3_eventCancel(); |
|
4260 } |
|
4261 } |
|
4262 |
|
4263 var d3_svg_brushCursor = { |
|
4264 n: "ns-resize", |
|
4265 e: "ew-resize", |
|
4266 s: "ns-resize", |
|
4267 w: "ew-resize", |
|
4268 nw: "nwse-resize", |
|
4269 ne: "nesw-resize", |
|
4270 se: "nwse-resize", |
|
4271 sw: "nesw-resize" |
|
4272 }; |
|
4273 d3.behavior = {}; |
|
4274 d3.behavior.drag = function() { |
|
4275 var event = d3.dispatch("drag", "dragstart", "dragend"); |
|
4276 |
|
4277 function drag() { |
|
4278 this |
|
4279 .on("mousedown.drag", mousedown) |
|
4280 .on("touchstart.drag", mousedown); |
|
4281 |
|
4282 d3.select(window) |
|
4283 .on("mousemove.drag", d3_behavior_dragMove) |
|
4284 .on("touchmove.drag", d3_behavior_dragMove) |
|
4285 .on("mouseup.drag", d3_behavior_dragUp, true) |
|
4286 .on("touchend.drag", d3_behavior_dragUp, true) |
|
4287 .on("click.drag", d3_behavior_dragClick, true); |
|
4288 } |
|
4289 |
|
4290 // snapshot the local context for subsequent dispatch |
|
4291 function start() { |
|
4292 d3_behavior_dragEvent = event; |
|
4293 d3_behavior_dragEventTarget = d3.event.target; |
|
4294 d3_behavior_dragOffset = d3_behavior_dragPoint((d3_behavior_dragTarget = this).parentNode); |
|
4295 d3_behavior_dragMoved = 0; |
|
4296 d3_behavior_dragArguments = arguments; |
|
4297 } |
|
4298 |
|
4299 function mousedown() { |
|
4300 start.apply(this, arguments); |
|
4301 d3_behavior_dragDispatch("dragstart"); |
|
4302 } |
|
4303 |
|
4304 drag.on = function(type, listener) { |
|
4305 event.on(type, listener); |
|
4306 return drag; |
|
4307 }; |
|
4308 |
|
4309 return drag; |
|
4310 }; |
|
4311 |
|
4312 var d3_behavior_dragEvent, |
|
4313 d3_behavior_dragEventTarget, |
|
4314 d3_behavior_dragTarget, |
|
4315 d3_behavior_dragArguments, |
|
4316 d3_behavior_dragOffset, |
|
4317 d3_behavior_dragMoved, |
|
4318 d3_behavior_dragStopClick; |
|
4319 |
|
4320 function d3_behavior_dragDispatch(type) { |
|
4321 var o = d3.event, p = d3_behavior_dragTarget.parentNode, dx = 0, dy = 0; |
|
4322 |
|
4323 if (p) { |
|
4324 p = d3_behavior_dragPoint(p); |
|
4325 dx = p[0] - d3_behavior_dragOffset[0]; |
|
4326 dy = p[1] - d3_behavior_dragOffset[1]; |
|
4327 d3_behavior_dragOffset = p; |
|
4328 d3_behavior_dragMoved |= dx | dy; |
|
4329 } |
|
4330 |
|
4331 try { |
|
4332 d3.event = {dx: dx, dy: dy}; |
|
4333 d3_behavior_dragEvent[type].apply(d3_behavior_dragTarget, d3_behavior_dragArguments); |
|
4334 } finally { |
|
4335 d3.event = o; |
|
4336 } |
|
4337 |
|
4338 o.preventDefault(); |
|
4339 } |
|
4340 |
|
4341 function d3_behavior_dragPoint(container, type) { |
|
4342 // TODO Track touch points by identifier. |
|
4343 var t = d3.event.changedTouches; |
|
4344 return t ? d3.svg.touches(container, t)[0] : d3.svg.mouse(container); |
|
4345 } |
|
4346 |
|
4347 function d3_behavior_dragMove() { |
|
4348 if (!d3_behavior_dragTarget) return; |
|
4349 var parent = d3_behavior_dragTarget.parentNode; |
|
4350 |
|
4351 // O NOES! The drag element was removed from the DOM. |
|
4352 if (!parent) return d3_behavior_dragUp(); |
|
4353 |
|
4354 d3_behavior_dragDispatch("drag"); |
|
4355 d3_eventCancel(); |
|
4356 } |
|
4357 |
|
4358 function d3_behavior_dragUp() { |
|
4359 if (!d3_behavior_dragTarget) return; |
|
4360 d3_behavior_dragDispatch("dragend"); |
|
4361 d3_behavior_dragTarget = null; |
|
4362 |
|
4363 // If the node was moved, prevent the mouseup from propagating. |
|
4364 // Also prevent the subsequent click from propagating (e.g., for anchors). |
|
4365 if (d3_behavior_dragMoved && d3_behavior_dragEventTarget === d3.event.target) { |
|
4366 d3_behavior_dragStopClick = true; |
|
4367 d3_eventCancel(); |
|
4368 } |
|
4369 } |
|
4370 |
|
4371 function d3_behavior_dragClick() { |
|
4372 if (d3_behavior_dragStopClick && d3_behavior_dragEventTarget === d3.event.target) { |
|
4373 d3_eventCancel(); |
|
4374 d3_behavior_dragStopClick = false; |
|
4375 d3_behavior_dragEventTarget = null; |
|
4376 } |
|
4377 } |
|
4378 // TODO unbind zoom behavior? |
|
4379 d3.behavior.zoom = function() { |
|
4380 var xyz = [0, 0, 0], |
|
4381 event = d3.dispatch("zoom"), |
|
4382 extent = d3_behavior_zoomInfiniteExtent; |
|
4383 |
|
4384 function zoom() { |
|
4385 this |
|
4386 .on("mousedown.zoom", mousedown) |
|
4387 .on("mousewheel.zoom", mousewheel) |
|
4388 .on("DOMMouseScroll.zoom", mousewheel) |
|
4389 .on("dblclick.zoom", dblclick) |
|
4390 .on("touchstart.zoom", touchstart); |
|
4391 |
|
4392 d3.select(window) |
|
4393 .on("mousemove.zoom", d3_behavior_zoomMousemove) |
|
4394 .on("mouseup.zoom", d3_behavior_zoomMouseup) |
|
4395 .on("touchmove.zoom", d3_behavior_zoomTouchmove) |
|
4396 .on("touchend.zoom", d3_behavior_zoomTouchup) |
|
4397 .on("click.zoom", d3_behavior_zoomClick, true); |
|
4398 } |
|
4399 |
|
4400 // snapshot the local context for subsequent dispatch |
|
4401 function start() { |
|
4402 d3_behavior_zoomXyz = xyz; |
|
4403 d3_behavior_zoomExtent = extent; |
|
4404 d3_behavior_zoomDispatch = event.zoom; |
|
4405 d3_behavior_zoomEventTarget = d3.event.target; |
|
4406 d3_behavior_zoomTarget = this; |
|
4407 d3_behavior_zoomArguments = arguments; |
|
4408 } |
|
4409 |
|
4410 function mousedown() { |
|
4411 start.apply(this, arguments); |
|
4412 d3_behavior_zoomPanning = d3_behavior_zoomLocation(d3.svg.mouse(d3_behavior_zoomTarget)); |
|
4413 d3_behavior_zoomMoved = false; |
|
4414 d3.event.preventDefault(); |
|
4415 window.focus(); |
|
4416 } |
|
4417 |
|
4418 // store starting mouse location |
|
4419 function mousewheel() { |
|
4420 start.apply(this, arguments); |
|
4421 if (!d3_behavior_zoomZooming) d3_behavior_zoomZooming = d3_behavior_zoomLocation(d3.svg.mouse(d3_behavior_zoomTarget)); |
|
4422 d3_behavior_zoomTo(d3_behavior_zoomDelta() + xyz[2], d3.svg.mouse(d3_behavior_zoomTarget), d3_behavior_zoomZooming); |
|
4423 } |
|
4424 |
|
4425 function dblclick() { |
|
4426 start.apply(this, arguments); |
|
4427 var mouse = d3.svg.mouse(d3_behavior_zoomTarget); |
|
4428 d3_behavior_zoomTo(d3.event.shiftKey ? Math.ceil(xyz[2] - 1) : Math.floor(xyz[2] + 1), mouse, d3_behavior_zoomLocation(mouse)); |
|
4429 } |
|
4430 |
|
4431 // doubletap detection |
|
4432 function touchstart() { |
|
4433 start.apply(this, arguments); |
|
4434 var touches = d3_behavior_zoomTouchup(), |
|
4435 touch, |
|
4436 now = Date.now(); |
|
4437 if ((touches.length === 1) && (now - d3_behavior_zoomLast < 300)) { |
|
4438 d3_behavior_zoomTo(1 + Math.floor(xyz[2]), touch = touches[0], d3_behavior_zoomLocations[touch.identifier]); |
|
4439 } |
|
4440 d3_behavior_zoomLast = now; |
|
4441 } |
|
4442 |
|
4443 zoom.extent = function(x) { |
|
4444 if (!arguments.length) return extent; |
|
4445 extent = x == null ? d3_behavior_zoomInfiniteExtent : x; |
|
4446 return zoom; |
|
4447 }; |
|
4448 |
|
4449 zoom.on = function(type, listener) { |
|
4450 event.on(type, listener); |
|
4451 return zoom; |
|
4452 }; |
|
4453 |
|
4454 return zoom; |
|
4455 }; |
|
4456 |
|
4457 var d3_behavior_zoomDiv, |
|
4458 d3_behavior_zoomPanning, |
|
4459 d3_behavior_zoomZooming, |
|
4460 d3_behavior_zoomLocations = {}, // identifier -> location |
|
4461 d3_behavior_zoomLast = 0, |
|
4462 d3_behavior_zoomXyz, |
|
4463 d3_behavior_zoomExtent, |
|
4464 d3_behavior_zoomDispatch, |
|
4465 d3_behavior_zoomEventTarget, |
|
4466 d3_behavior_zoomTarget, |
|
4467 d3_behavior_zoomArguments, |
|
4468 d3_behavior_zoomMoved, |
|
4469 d3_behavior_zoomStopClick; |
|
4470 |
|
4471 function d3_behavior_zoomLocation(point) { |
|
4472 return [ |
|
4473 point[0] - d3_behavior_zoomXyz[0], |
|
4474 point[1] - d3_behavior_zoomXyz[1], |
|
4475 d3_behavior_zoomXyz[2] |
|
4476 ]; |
|
4477 } |
|
4478 |
|
4479 // detect the pixels that would be scrolled by this wheel event |
|
4480 function d3_behavior_zoomDelta() { |
|
4481 |
|
4482 // mousewheel events are totally broken! |
|
4483 // https://bugs.webkit.org/show_bug.cgi?id=40441 |
|
4484 // not only that, but Chrome and Safari differ in re. to acceleration! |
|
4485 if (!d3_behavior_zoomDiv) { |
|
4486 d3_behavior_zoomDiv = d3.select("body").append("div") |
|
4487 .style("visibility", "hidden") |
|
4488 .style("top", 0) |
|
4489 .style("height", 0) |
|
4490 .style("width", 0) |
|
4491 .style("overflow-y", "scroll") |
|
4492 .append("div") |
|
4493 .style("height", "2000px") |
|
4494 .node().parentNode; |
|
4495 } |
|
4496 |
|
4497 var e = d3.event, delta; |
|
4498 try { |
|
4499 d3_behavior_zoomDiv.scrollTop = 1000; |
|
4500 d3_behavior_zoomDiv.dispatchEvent(e); |
|
4501 delta = 1000 - d3_behavior_zoomDiv.scrollTop; |
|
4502 } catch (error) { |
|
4503 delta = e.wheelDelta || (-e.detail * 5); |
|
4504 } |
|
4505 |
|
4506 return delta * .005; |
|
4507 } |
|
4508 |
|
4509 // Note: Since we don't rotate, it's possible for the touches to become |
|
4510 // slightly detached from their original positions. Thus, we recompute the |
|
4511 // touch points on touchend as well as touchstart! |
|
4512 function d3_behavior_zoomTouchup() { |
|
4513 var touches = d3.svg.touches(d3_behavior_zoomTarget), |
|
4514 i = -1, |
|
4515 n = touches.length, |
|
4516 touch; |
|
4517 while (++i < n) d3_behavior_zoomLocations[(touch = touches[i]).identifier] = d3_behavior_zoomLocation(touch); |
|
4518 return touches; |
|
4519 } |
|
4520 |
|
4521 function d3_behavior_zoomTouchmove() { |
|
4522 var touches = d3.svg.touches(d3_behavior_zoomTarget); |
|
4523 switch (touches.length) { |
|
4524 |
|
4525 // single-touch pan |
|
4526 case 1: { |
|
4527 var touch = touches[0]; |
|
4528 d3_behavior_zoomTo(d3_behavior_zoomXyz[2], touch, d3_behavior_zoomLocations[touch.identifier]); |
|
4529 break; |
|
4530 } |
|
4531 |
|
4532 // double-touch pan + zoom |
|
4533 case 2: { |
|
4534 var p0 = touches[0], |
|
4535 p1 = touches[1], |
|
4536 p2 = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2], |
|
4537 l0 = d3_behavior_zoomLocations[p0.identifier], |
|
4538 l1 = d3_behavior_zoomLocations[p1.identifier], |
|
4539 l2 = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2, l0[2]]; |
|
4540 d3_behavior_zoomTo(Math.log(d3.event.scale) / Math.LN2 + l0[2], p2, l2); |
|
4541 break; |
|
4542 } |
|
4543 } |
|
4544 } |
|
4545 |
|
4546 function d3_behavior_zoomMousemove() { |
|
4547 d3_behavior_zoomZooming = null; |
|
4548 if (d3_behavior_zoomPanning) { |
|
4549 d3_behavior_zoomMoved = true; |
|
4550 d3_behavior_zoomTo(d3_behavior_zoomXyz[2], d3.svg.mouse(d3_behavior_zoomTarget), d3_behavior_zoomPanning); |
|
4551 } |
|
4552 } |
|
4553 |
|
4554 function d3_behavior_zoomMouseup() { |
|
4555 if (d3_behavior_zoomPanning) { |
|
4556 if (d3_behavior_zoomMoved && d3_behavior_zoomEventTarget === d3.event.target) { |
|
4557 d3_behavior_zoomStopClick = true; |
|
4558 } |
|
4559 d3_behavior_zoomMousemove(); |
|
4560 d3_behavior_zoomPanning = null; |
|
4561 } |
|
4562 } |
|
4563 |
|
4564 function d3_behavior_zoomClick() { |
|
4565 if (d3_behavior_zoomStopClick && d3_behavior_zoomEventTarget === d3.event.target) { |
|
4566 d3.event.stopPropagation(); |
|
4567 d3.event.preventDefault(); |
|
4568 d3_behavior_zoomStopClick = false; |
|
4569 d3_behavior_zoomEventTarget = null; |
|
4570 } |
|
4571 } |
|
4572 |
|
4573 function d3_behavior_zoomTo(z, x0, x1) { |
|
4574 z = d3_behavior_zoomExtentClamp(z, 2); |
|
4575 var j = Math.pow(2, d3_behavior_zoomXyz[2]), |
|
4576 k = Math.pow(2, z), |
|
4577 K = Math.pow(2, (d3_behavior_zoomXyz[2] = z) - x1[2]), |
|
4578 x_ = d3_behavior_zoomXyz[0], |
|
4579 y_ = d3_behavior_zoomXyz[1], |
|
4580 x = d3_behavior_zoomXyz[0] = d3_behavior_zoomExtentClamp((x0[0] - x1[0] * K), 0, k), |
|
4581 y = d3_behavior_zoomXyz[1] = d3_behavior_zoomExtentClamp((x0[1] - x1[1] * K), 1, k), |
|
4582 o = d3.event; // Events can be reentrant (e.g., focus). |
|
4583 |
|
4584 d3.event = { |
|
4585 scale: k, |
|
4586 translate: [x, y], |
|
4587 transform: function(sx, sy) { |
|
4588 if (sx) transform(sx, x_, x); |
|
4589 if (sy) transform(sy, y_, y); |
|
4590 } |
|
4591 }; |
|
4592 |
|
4593 function transform(scale, a, b) { |
|
4594 scale.domain(scale.range().map(function(v) { return scale.invert(((v - b) * j) / k + a); })); |
|
4595 } |
|
4596 |
|
4597 try { |
|
4598 d3_behavior_zoomDispatch.apply(d3_behavior_zoomTarget, d3_behavior_zoomArguments); |
|
4599 } finally { |
|
4600 d3.event = o; |
|
4601 } |
|
4602 |
|
4603 o.preventDefault(); |
|
4604 } |
|
4605 |
|
4606 var d3_behavior_zoomInfiniteExtent = [ |
|
4607 [-Infinity, Infinity], |
|
4608 [-Infinity, Infinity], |
|
4609 [-Infinity, Infinity] |
|
4610 ]; |
|
4611 |
|
4612 function d3_behavior_zoomExtentClamp(x, i, k) { |
|
4613 var range = d3_behavior_zoomExtent[i], |
|
4614 r0 = range[0], |
|
4615 r1 = range[1]; |
|
4616 return arguments.length === 3 |
|
4617 ? Math.max(r1 * (r1 === Infinity ? -Infinity : 1 / k - 1), |
|
4618 Math.min(r0 === -Infinity ? Infinity : r0, x / k)) * k |
|
4619 : Math.max(r0, Math.min(r1, x)); |
|
4620 } |
|
4621 })(); |