[76] | 1 | d3.scale.linear = function() { |
---|
| 2 | var domain = [0, 1], |
---|
| 3 | range = [0, 1], |
---|
| 4 | interpolate = d3.interpolate, |
---|
| 5 | clamp = false, |
---|
| 6 | output, |
---|
| 7 | input; |
---|
| 8 | |
---|
| 9 | function rescale() { |
---|
| 10 | var linear = domain.length == 2 ? d3_scale_bilinear : d3_scale_polylinear, |
---|
| 11 | uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber; |
---|
| 12 | output = linear(domain, range, uninterpolate, interpolate); |
---|
| 13 | input = linear(range, domain, uninterpolate, d3.interpolate); |
---|
| 14 | return scale; |
---|
| 15 | } |
---|
| 16 | |
---|
| 17 | function scale(x) { |
---|
| 18 | return output(x); |
---|
| 19 | } |
---|
| 20 | |
---|
| 21 | // Note: requires range is coercible to number! |
---|
| 22 | scale.invert = function(y) { |
---|
| 23 | return input(y); |
---|
| 24 | }; |
---|
| 25 | |
---|
| 26 | scale.domain = function(x) { |
---|
| 27 | if (!arguments.length) return domain; |
---|
| 28 | domain = x.map(Number); |
---|
| 29 | return rescale(); |
---|
| 30 | }; |
---|
| 31 | |
---|
| 32 | scale.range = function(x) { |
---|
| 33 | if (!arguments.length) return range; |
---|
| 34 | range = x; |
---|
| 35 | return rescale(); |
---|
| 36 | }; |
---|
| 37 | |
---|
| 38 | scale.rangeRound = function(x) { |
---|
| 39 | return scale.range(x).interpolate(d3.interpolateRound); |
---|
| 40 | }; |
---|
| 41 | |
---|
| 42 | scale.clamp = function(x) { |
---|
| 43 | if (!arguments.length) return clamp; |
---|
| 44 | clamp = x; |
---|
| 45 | return rescale(); |
---|
| 46 | }; |
---|
| 47 | |
---|
| 48 | scale.interpolate = function(x) { |
---|
| 49 | if (!arguments.length) return interpolate; |
---|
| 50 | interpolate = x; |
---|
| 51 | return rescale(); |
---|
| 52 | }; |
---|
| 53 | |
---|
| 54 | scale.ticks = function(m) { |
---|
| 55 | return d3_scale_linearTicks(domain, m); |
---|
| 56 | }; |
---|
| 57 | |
---|
| 58 | scale.tickFormat = function(m) { |
---|
| 59 | return d3_scale_linearTickFormat(domain, m); |
---|
| 60 | }; |
---|
| 61 | |
---|
| 62 | scale.nice = function() { |
---|
| 63 | d3_scale_nice(domain, d3_scale_linearNice); |
---|
| 64 | return rescale(); |
---|
| 65 | }; |
---|
| 66 | |
---|
| 67 | return rescale(); |
---|
| 68 | }; |
---|
| 69 | |
---|
| 70 | function d3_scale_linearRebind(scale, linear) { |
---|
| 71 | scale.range = d3.rebind(scale, linear.range); |
---|
| 72 | scale.rangeRound = d3.rebind(scale, linear.rangeRound); |
---|
| 73 | scale.interpolate = d3.rebind(scale, linear.interpolate); |
---|
| 74 | scale.clamp = d3.rebind(scale, linear.clamp); |
---|
| 75 | return scale; |
---|
| 76 | } |
---|
| 77 | |
---|
| 78 | function d3_scale_linearNice(dx) { |
---|
| 79 | dx = Math.pow(10, Math.round(Math.log(dx) / Math.LN10) - 1); |
---|
| 80 | return { |
---|
| 81 | floor: function(x) { return Math.floor(x / dx) * dx; }, |
---|
| 82 | ceil: function(x) { return Math.ceil(x / dx) * dx; } |
---|
| 83 | }; |
---|
| 84 | } |
---|
| 85 | |
---|
| 86 | // TODO Dates? Ugh. |
---|
| 87 | function d3_scale_linearTickRange(domain, m) { |
---|
| 88 | var extent = d3_scaleExtent(domain), |
---|
| 89 | span = extent[1] - extent[0], |
---|
| 90 | step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), |
---|
| 91 | err = m / span * step; |
---|
| 92 | |
---|
| 93 | // Filter ticks to get closer to the desired count. |
---|
| 94 | if (err <= .15) step *= 10; |
---|
| 95 | else if (err <= .35) step *= 5; |
---|
| 96 | else if (err <= .75) step *= 2; |
---|
| 97 | |
---|
| 98 | // Round start and stop values to step interval. |
---|
| 99 | extent[0] = Math.ceil(extent[0] / step) * step; |
---|
| 100 | extent[1] = Math.floor(extent[1] / step) * step + step * .5; // inclusive |
---|
| 101 | extent[2] = step; |
---|
| 102 | return extent; |
---|
| 103 | } |
---|
| 104 | |
---|
| 105 | function d3_scale_linearTicks(domain, m) { |
---|
| 106 | return d3.range.apply(d3, d3_scale_linearTickRange(domain, m)); |
---|
| 107 | } |
---|
| 108 | |
---|
| 109 | function d3_scale_linearTickFormat(domain, m) { |
---|
| 110 | return d3.format(",." + Math.max(0, -Math.floor(Math.log(d3_scale_linearTickRange(domain, m)[2]) / Math.LN10 + .01)) + "f"); |
---|
| 111 | } |
---|