source: node_modules/d3-scale/src/log.js@ e4c61dd

Last change on this file since e4c61dd was e4c61dd, checked in by istevanoska <ilinastevanoska@…>, 6 months ago

Prototype 1.1

  • Property mode set to 100644
File size: 3.4 KB
Line 
1import {ticks} from "d3-array";
2import {format, formatSpecifier} from "d3-format";
3import nice from "./nice.js";
4import {copy, transformer} from "./continuous.js";
5import {initRange} from "./init.js";
6
7function transformLog(x) {
8 return Math.log(x);
9}
10
11function transformExp(x) {
12 return Math.exp(x);
13}
14
15function transformLogn(x) {
16 return -Math.log(-x);
17}
18
19function transformExpn(x) {
20 return -Math.exp(-x);
21}
22
23function pow10(x) {
24 return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x;
25}
26
27function powp(base) {
28 return base === 10 ? pow10
29 : base === Math.E ? Math.exp
30 : x => Math.pow(base, x);
31}
32
33function logp(base) {
34 return base === Math.E ? Math.log
35 : base === 10 && Math.log10
36 || base === 2 && Math.log2
37 || (base = Math.log(base), x => Math.log(x) / base);
38}
39
40function reflect(f) {
41 return (x, k) => -f(-x, k);
42}
43
44export function loggish(transform) {
45 const scale = transform(transformLog, transformExp);
46 const domain = scale.domain;
47 let base = 10;
48 let logs;
49 let pows;
50
51 function rescale() {
52 logs = logp(base), pows = powp(base);
53 if (domain()[0] < 0) {
54 logs = reflect(logs), pows = reflect(pows);
55 transform(transformLogn, transformExpn);
56 } else {
57 transform(transformLog, transformExp);
58 }
59 return scale;
60 }
61
62 scale.base = function(_) {
63 return arguments.length ? (base = +_, rescale()) : base;
64 };
65
66 scale.domain = function(_) {
67 return arguments.length ? (domain(_), rescale()) : domain();
68 };
69
70 scale.ticks = count => {
71 const d = domain();
72 let u = d[0];
73 let v = d[d.length - 1];
74 const r = v < u;
75
76 if (r) ([u, v] = [v, u]);
77
78 let i = logs(u);
79 let j = logs(v);
80 let k;
81 let t;
82 const n = count == null ? 10 : +count;
83 let z = [];
84
85 if (!(base % 1) && j - i < n) {
86 i = Math.floor(i), j = Math.ceil(j);
87 if (u > 0) for (; i <= j; ++i) {
88 for (k = 1; k < base; ++k) {
89 t = i < 0 ? k / pows(-i) : k * pows(i);
90 if (t < u) continue;
91 if (t > v) break;
92 z.push(t);
93 }
94 } else for (; i <= j; ++i) {
95 for (k = base - 1; k >= 1; --k) {
96 t = i > 0 ? k / pows(-i) : k * pows(i);
97 if (t < u) continue;
98 if (t > v) break;
99 z.push(t);
100 }
101 }
102 if (z.length * 2 < n) z = ticks(u, v, n);
103 } else {
104 z = ticks(i, j, Math.min(j - i, n)).map(pows);
105 }
106 return r ? z.reverse() : z;
107 };
108
109 scale.tickFormat = (count, specifier) => {
110 if (count == null) count = 10;
111 if (specifier == null) specifier = base === 10 ? "s" : ",";
112 if (typeof specifier !== "function") {
113 if (!(base % 1) && (specifier = formatSpecifier(specifier)).precision == null) specifier.trim = true;
114 specifier = format(specifier);
115 }
116 if (count === Infinity) return specifier;
117 const k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate?
118 return d => {
119 let i = d / pows(Math.round(logs(d)));
120 if (i * base < base - 0.5) i *= base;
121 return i <= k ? specifier(d) : "";
122 };
123 };
124
125 scale.nice = () => {
126 return domain(nice(domain(), {
127 floor: x => pows(Math.floor(logs(x))),
128 ceil: x => pows(Math.ceil(logs(x)))
129 }));
130 };
131
132 return scale;
133}
134
135export default function log() {
136 const scale = loggish(transformer()).domain([1, 10]);
137 scale.copy = () => copy(scale, log()).base(scale.base());
138 initRange.apply(scale, arguments);
139 return scale;
140}
Note: See TracBrowser for help on using the repository browser.