gridviz 3.0.19 → 3.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +128 -128
  2. package/dist/gridviz.js +7861 -7861
  3. package/dist/gridviz.min.js +1 -1
  4. package/package.json +74 -74
  5. package/src/button/ZoomButtons.js +101 -101
  6. package/src/core/Dataset.js +154 -154
  7. package/src/core/Drawable.js +60 -60
  8. package/src/core/GeoCanvas.js +430 -430
  9. package/src/core/Layer.js +23 -23
  10. package/src/core/Legend.js +108 -108
  11. package/src/core/Map.js +516 -516
  12. package/src/core/MultiResolutionDataset.js +93 -93
  13. package/src/core/Style.js +98 -98
  14. package/src/dataset/CSVGrid.js +112 -112
  15. package/src/dataset/GeoTIFF.js +122 -122
  16. package/src/dataset/JSGrid.js +55 -55
  17. package/src/dataset/TiledGrid.js +302 -302
  18. package/src/dataset/worker.js +18 -18
  19. package/src/index.js +77 -77
  20. package/src/layer/BackgroundLayer.js +162 -162
  21. package/src/layer/BackgroundLayerImage.js +81 -81
  22. package/src/layer/BackgroundLayerWMS.js +104 -104
  23. package/src/layer/GeoJSONLayer.js +214 -214
  24. package/src/layer/GridLayer.js +148 -148
  25. package/src/layer/LabelLayer.js +194 -194
  26. package/src/legend/ColorCategoryLegend.js +109 -109
  27. package/src/legend/ColorDiscreteLegend.js +100 -100
  28. package/src/legend/ColorLegend.js +115 -115
  29. package/src/legend/OrientationLegend.js +89 -89
  30. package/src/legend/SizeLegend.js +224 -224
  31. package/src/legend/TernaryLegend.js +302 -302
  32. package/src/style/CompositionStyle.js +291 -291
  33. package/src/style/DotDensityStyle.js +133 -133
  34. package/src/style/ImageStyle.js +100 -100
  35. package/src/style/IsoFenceStyle.js +217 -217
  36. package/src/style/JoyPlotStyle.js +127 -127
  37. package/src/style/LegoStyle.js +110 -110
  38. package/src/style/MosaicStyle.js +99 -99
  39. package/src/style/NinjaStarStyle.js +102 -102
  40. package/src/style/PillarStyle.js +207 -207
  41. package/src/style/SegmentStyle.js +105 -105
  42. package/src/style/ShapeColorSizeStyle.js +147 -147
  43. package/src/style/SideCategoryStyle.js +112 -112
  44. package/src/style/SideStyle.js +212 -212
  45. package/src/style/SquareColorCategoryWebGLStyle.js +107 -107
  46. package/src/style/SquareColorWebGLStyle.js +126 -126
  47. package/src/style/StrokeStyle.js +135 -135
  48. package/src/style/TanakaStyle.js +69 -69
  49. package/src/style/TextStyle.js +110 -110
  50. package/src/style/TimeSeriesStyle.js +222 -222
  51. package/src/utils/scale.js +218 -218
  52. package/src/utils/stretching.js +120 -120
  53. package/src/utils/ternary.js +208 -208
  54. package/src/utils/utils.js +58 -58
  55. package/src/utils/webGLUtils.js +72 -72
@@ -1,208 +1,208 @@
1
- //@ts-check
2
- 'use strict'
3
-
4
- import { interpolateLab } from 'd3-interpolate'
5
-
6
- export const ternaryClassifier = (properties, totalFunction, opts = {}) => {
7
- //the three properties
8
- const p0 = properties[0],
9
- p1 = properties[1],
10
- p2 = properties[2]
11
-
12
- //the classifier center point. sum must be equal to 1
13
- const [c0, c1, c2] = opts.center || [1 / 3, 1 / 3, 1 / 3]
14
-
15
- //parameter to decide wether to use mixed classes m0, m1, m2.
16
- const withMixedClasses = opts.withMixedClasses != undefined ? opts.withMixedClasses : true
17
-
18
- //parameter to decide wether to use a central class, and the size of this central class.
19
- //set to 0 or undefined for not showing any central class. Set to 1 for a central class that contains the mix classes
20
- const cc = opts.centerCoefficient ? 1 - opts.centerCoefficient : undefined
21
-
22
- //the output classifier method
23
- const fun = (c) => {
24
- //get total
25
- const tot = totalFunction(c)
26
- if (!tot) return undefined
27
- //compute shares
28
- const [s0, s1, s2] = [+c[p0] / tot, +c[p1] / tot, +c[p2] / tot]
29
-
30
- //class 0
31
- if (s0 >= c0 && s1 <= c1 && s2 <= c2) {
32
- //central class near class 0
33
- if (cc != undefined && (s2 - c2) * (c1 - cc * c1) >= (s1 - cc * c1) * (cc * c2 - c2))
34
- return 'center'
35
- return '0'
36
- }
37
- //class 1
38
- if (s0 <= c0 && s1 >= c1 && s2 <= c2) {
39
- //central class near class 1
40
- if (cc != undefined && (s2 - c2) * (c0 - cc * c0) >= (s0 - cc * c0) * (cc * c2 - c2))
41
- return 'center'
42
- return '1'
43
- }
44
- //class 2
45
- if (s0 <= c0 && s1 <= c1 && s2 >= c2) {
46
- //central class near class 2
47
- if (cc != undefined && (s1 - c1) * (c0 - cc * c0) >= (s0 - cc * c0) * (cc * c1 - c1))
48
- return 'center'
49
- return '2'
50
- }
51
- //middle class 0 - intersection class 1 and 2
52
- if (s0 <= c0 && s1 >= c1 && s2 >= c2) {
53
- //central class
54
- if (cc != undefined && s0 > cc * c0) return 'center'
55
- if (withMixedClasses) return 'm12'
56
- return s1 > s2 ? '1' : '2'
57
- }
58
- //middle class 1 - intersection class 0 and 1
59
- if (s0 >= c0 && s1 <= c1 && s2 >= c2) {
60
- //central class
61
- if (cc != undefined && s1 > cc * c1) return 'center'
62
- if (withMixedClasses) return 'm02'
63
- return s0 > s2 ? '0' : '2'
64
- }
65
- //middle class 2 - intersection class 0 and 1
66
- if (s0 >= c0 && s1 >= c1 && s2 <= c2) {
67
- //central class
68
- if (cc != undefined && s2 > cc * c2) return 'center'
69
- if (withMixedClasses) return 'm01'
70
- return s1 > s0 ? '1' : '0'
71
- }
72
- //should not happen
73
- return 'unknown'
74
- }
75
-
76
- //attach information to output function
77
- fun.center = [c0, c1, c2]
78
- fun.centerCoefficient = opts.centerCoefficient
79
-
80
- return fun
81
- }
82
-
83
- export const ternaryColorClassifier = (properties, totalFunction, colors, opts = {}) => {
84
- //the three colors
85
- const [color0, color1, color2] = colors || ['red', 'green', 'blue']
86
-
87
- //the color interpolation function
88
- const colorInterpolation = opts.colorInterpolation || interpolateLab
89
-
90
- //parameter to decide wether to use mixed classes.
91
- const withMixedClasses = opts.withMixedClasses != undefined ? opts.withMixedClasses : true
92
- //https://d3js.org/d3-interpolate/color
93
- const mixColorFunction = (color1, color2) => colorInterpolation(color1, color2)(0.5)
94
- //the colors corresponding to the mixed classes
95
- const [mixColor0, mixColor1, mixColor2] =
96
- opts.mixedColors || withMixedClasses
97
- ? [
98
- mixColorFunction(color1, color2),
99
- mixColorFunction(color0, color2),
100
- mixColorFunction(color0, color1),
101
- ]
102
- : []
103
-
104
- //the central color, used for the central class, if any. The central class is the class of relatively balanced values, around the center point
105
- const centerColor =
106
- opts.centerColor || colorInterpolation(mixColorFunction(color0, color1), color2)(0.333)
107
-
108
- //make classifier
109
- const classifier = ternaryClassifier(properties, totalFunction, opts)
110
-
111
- //the output color classifier method
112
- const fun = (c) => {
113
- const cla = classifier(c)
114
- if (cla == '0') return color0
115
- if (cla == '1') return color1
116
- if (cla == '2') return color2
117
- if (cla == 'm12') return mixColor0
118
- if (cla == 'm02') return mixColor1
119
- if (cla == 'm01') return mixColor2
120
- if (cla == 'center') return centerColor
121
- return opts.defaultColor || 'black'
122
- }
123
- fun.center = classifier.center
124
- fun.centerCoefficient = opts.centerCoefficient
125
- fun.colors = [color0, color1, color2]
126
- fun.mixColors = [mixColor0, mixColor1, mixColor2]
127
- fun.centerColor = centerColor
128
- fun.classifier = classifier
129
-
130
- return fun
131
- }
132
-
133
-
134
-
135
-
136
- // OLD VERSIONS
137
-
138
- /*
139
- const orderedIndexesDec = arr => [...arr.keys()].sort((a, b) => arr[b] - arr[a]);
140
- const orderedIndexesInc = arr => [...arr.keys()].sort((a, b) => arr[a] - arr[b]);
141
-
142
- export const ternaryClassifier = (properties, totalFunction, opts = {}) => {
143
- const lowThreshold = opts.lowThreshold || [1 / 3, 1 / 3, 1 / 3]
144
- const highThreshold = opts.highThreshold || [2 / 3, 2 / 3, 2 / 3]
145
- const colors = opts.colors || ["red", "green", "blue"]
146
- const colorInterpolation = opts.colorInterpolation || interpolateLab
147
-
148
- //https://d3js.org/d3-interpolate/color
149
- const middleColorFunction = (color1, color2) => colorInterpolation(color1, color2)(0.5)
150
- const middleColors = opts.middleColors || [middleColorFunction(colors[1], colors[2]), middleColorFunction(colors[0], colors[2]), middleColorFunction(colors[0], colors[1])]
151
- const centerColor = opts.centerColor || colorInterpolation(middleColors[2], colors[2])(0.333)
152
-
153
- const high_ = orderedIndexesDec(highThreshold)
154
- const low_ = orderedIndexesInc(lowThreshold)
155
-
156
- const p0 = properties[0], p1 = properties[1], p2 = properties[2]
157
- const fun = c => {
158
- //get total
159
- const tot = totalFunction(c)
160
- if (!tot) return undefined
161
- //compute shares
162
- const shares = [+c[p0] / tot, +c[p1] / tot, +c[p2] / tot]
163
- //return colors
164
- //start first with the extreme high (triangles): from the larger value (small triangle) to the lower value (large triangle)
165
- for (let i of high_) if (shares[i] > highThreshold[i]) return colors[i]
166
- //then draw the extreme low (trapeziums): from the lower value (small trapeziums) to the larger values (large trapezium)
167
- for (let i of low_) if (shares[i] < lowThreshold[i]) return middleColors[i]
168
- //else central color
169
- return centerColor
170
- }
171
- fun.lowThreshold = lowThreshold
172
- fun.highThreshold = highThreshold
173
- fun.colors = colors
174
- fun.middleColors = middleColors
175
- fun.centerColor = centerColor
176
- fun.lowIndex = low_
177
- fun.highIndex = high_
178
- return fun
179
- }
180
- */
181
-
182
- /*
183
- export const ternaryClassifier3 = (properties, totalFunction, opts = {}) => {
184
- const [a01, a12, a20] = opts.thresholds || [1/3, 1/3, 1/3]
185
- const [c0, c1, c2] = opts.colors || ["red", "green", "blue"]
186
- const centerColor = opts.centerColor || "gray"
187
-
188
- const fff = a => a == 1 ? Infinity : a / (1 - a)
189
- const c01 = fff(a01), c12 = fff(a12), c20 = fff(a20)
190
-
191
- const p0 = properties[0], p1 = properties[1], p2 = properties[2]
192
- const fun = c => {
193
- //get total
194
- const tot = totalFunction(c)
195
- if (!tot) return undefined
196
- //compute shares
197
- const [s0, s1, s2] = [+c[p0] / tot, +c[p1] / tot, +c[p2] / tot]
198
- //return colors
199
- if (s0 * c01 > s1 && s0 > s2 * c20) return c0
200
- else if (s1 > s0 * c01 && s1 * c12 > s2) return c1
201
- else if (s2 * c20 > s0 && s2 > s1 * c12) return c2
202
- else return centerColor
203
- }
204
- fun.colors = [c0, c1, c2]
205
- fun.centerColor = centerColor
206
- return fun
207
- }
208
- */
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ import { interpolateLab } from 'd3-interpolate'
5
+
6
+ export const ternaryClassifier = (properties, totalFunction, opts = {}) => {
7
+ //the three properties
8
+ const p0 = properties[0],
9
+ p1 = properties[1],
10
+ p2 = properties[2]
11
+
12
+ //the classifier center point. sum must be equal to 1
13
+ const [c0, c1, c2] = opts.center || [1 / 3, 1 / 3, 1 / 3]
14
+
15
+ //parameter to decide wether to use mixed classes m0, m1, m2.
16
+ const withMixedClasses = opts.withMixedClasses != undefined ? opts.withMixedClasses : true
17
+
18
+ //parameter to decide wether to use a central class, and the size of this central class.
19
+ //set to 0 or undefined for not showing any central class. Set to 1 for a central class that contains the mix classes
20
+ const cc = opts.centerCoefficient ? 1 - opts.centerCoefficient : undefined
21
+
22
+ //the output classifier method
23
+ const fun = (c) => {
24
+ //get total
25
+ const tot = totalFunction(c)
26
+ if (!tot) return undefined
27
+ //compute shares
28
+ const [s0, s1, s2] = [+c[p0] / tot, +c[p1] / tot, +c[p2] / tot]
29
+
30
+ //class 0
31
+ if (s0 >= c0 && s1 <= c1 && s2 <= c2) {
32
+ //central class near class 0
33
+ if (cc != undefined && (s2 - c2) * (c1 - cc * c1) >= (s1 - cc * c1) * (cc * c2 - c2))
34
+ return 'center'
35
+ return '0'
36
+ }
37
+ //class 1
38
+ if (s0 <= c0 && s1 >= c1 && s2 <= c2) {
39
+ //central class near class 1
40
+ if (cc != undefined && (s2 - c2) * (c0 - cc * c0) >= (s0 - cc * c0) * (cc * c2 - c2))
41
+ return 'center'
42
+ return '1'
43
+ }
44
+ //class 2
45
+ if (s0 <= c0 && s1 <= c1 && s2 >= c2) {
46
+ //central class near class 2
47
+ if (cc != undefined && (s1 - c1) * (c0 - cc * c0) >= (s0 - cc * c0) * (cc * c1 - c1))
48
+ return 'center'
49
+ return '2'
50
+ }
51
+ //middle class 0 - intersection class 1 and 2
52
+ if (s0 <= c0 && s1 >= c1 && s2 >= c2) {
53
+ //central class
54
+ if (cc != undefined && s0 > cc * c0) return 'center'
55
+ if (withMixedClasses) return 'm12'
56
+ return s1 > s2 ? '1' : '2'
57
+ }
58
+ //middle class 1 - intersection class 0 and 1
59
+ if (s0 >= c0 && s1 <= c1 && s2 >= c2) {
60
+ //central class
61
+ if (cc != undefined && s1 > cc * c1) return 'center'
62
+ if (withMixedClasses) return 'm02'
63
+ return s0 > s2 ? '0' : '2'
64
+ }
65
+ //middle class 2 - intersection class 0 and 1
66
+ if (s0 >= c0 && s1 >= c1 && s2 <= c2) {
67
+ //central class
68
+ if (cc != undefined && s2 > cc * c2) return 'center'
69
+ if (withMixedClasses) return 'm01'
70
+ return s1 > s0 ? '1' : '0'
71
+ }
72
+ //should not happen
73
+ return 'unknown'
74
+ }
75
+
76
+ //attach information to output function
77
+ fun.center = [c0, c1, c2]
78
+ fun.centerCoefficient = opts.centerCoefficient
79
+
80
+ return fun
81
+ }
82
+
83
+ export const ternaryColorClassifier = (properties, totalFunction, colors, opts = {}) => {
84
+ //the three colors
85
+ const [color0, color1, color2] = colors || ['red', 'green', 'blue']
86
+
87
+ //the color interpolation function
88
+ const colorInterpolation = opts.colorInterpolation || interpolateLab
89
+
90
+ //parameter to decide wether to use mixed classes.
91
+ const withMixedClasses = opts.withMixedClasses != undefined ? opts.withMixedClasses : true
92
+ //https://d3js.org/d3-interpolate/color
93
+ const mixColorFunction = (color1, color2) => colorInterpolation(color1, color2)(0.5)
94
+ //the colors corresponding to the mixed classes
95
+ const [mixColor0, mixColor1, mixColor2] =
96
+ opts.mixedColors || withMixedClasses
97
+ ? [
98
+ mixColorFunction(color1, color2),
99
+ mixColorFunction(color0, color2),
100
+ mixColorFunction(color0, color1),
101
+ ]
102
+ : []
103
+
104
+ //the central color, used for the central class, if any. The central class is the class of relatively balanced values, around the center point
105
+ const centerColor =
106
+ opts.centerColor || colorInterpolation(mixColorFunction(color0, color1), color2)(0.333)
107
+
108
+ //make classifier
109
+ const classifier = ternaryClassifier(properties, totalFunction, opts)
110
+
111
+ //the output color classifier method
112
+ const fun = (c) => {
113
+ const cla = classifier(c)
114
+ if (cla == '0') return color0
115
+ if (cla == '1') return color1
116
+ if (cla == '2') return color2
117
+ if (cla == 'm12') return mixColor0
118
+ if (cla == 'm02') return mixColor1
119
+ if (cla == 'm01') return mixColor2
120
+ if (cla == 'center') return centerColor
121
+ return opts.defaultColor || 'black'
122
+ }
123
+ fun.center = classifier.center
124
+ fun.centerCoefficient = opts.centerCoefficient
125
+ fun.colors = [color0, color1, color2]
126
+ fun.mixColors = [mixColor0, mixColor1, mixColor2]
127
+ fun.centerColor = centerColor
128
+ fun.classifier = classifier
129
+
130
+ return fun
131
+ }
132
+
133
+
134
+
135
+
136
+ // OLD VERSIONS
137
+
138
+ /*
139
+ const orderedIndexesDec = arr => [...arr.keys()].sort((a, b) => arr[b] - arr[a]);
140
+ const orderedIndexesInc = arr => [...arr.keys()].sort((a, b) => arr[a] - arr[b]);
141
+
142
+ export const ternaryClassifier = (properties, totalFunction, opts = {}) => {
143
+ const lowThreshold = opts.lowThreshold || [1 / 3, 1 / 3, 1 / 3]
144
+ const highThreshold = opts.highThreshold || [2 / 3, 2 / 3, 2 / 3]
145
+ const colors = opts.colors || ["red", "green", "blue"]
146
+ const colorInterpolation = opts.colorInterpolation || interpolateLab
147
+
148
+ //https://d3js.org/d3-interpolate/color
149
+ const middleColorFunction = (color1, color2) => colorInterpolation(color1, color2)(0.5)
150
+ const middleColors = opts.middleColors || [middleColorFunction(colors[1], colors[2]), middleColorFunction(colors[0], colors[2]), middleColorFunction(colors[0], colors[1])]
151
+ const centerColor = opts.centerColor || colorInterpolation(middleColors[2], colors[2])(0.333)
152
+
153
+ const high_ = orderedIndexesDec(highThreshold)
154
+ const low_ = orderedIndexesInc(lowThreshold)
155
+
156
+ const p0 = properties[0], p1 = properties[1], p2 = properties[2]
157
+ const fun = c => {
158
+ //get total
159
+ const tot = totalFunction(c)
160
+ if (!tot) return undefined
161
+ //compute shares
162
+ const shares = [+c[p0] / tot, +c[p1] / tot, +c[p2] / tot]
163
+ //return colors
164
+ //start first with the extreme high (triangles): from the larger value (small triangle) to the lower value (large triangle)
165
+ for (let i of high_) if (shares[i] > highThreshold[i]) return colors[i]
166
+ //then draw the extreme low (trapeziums): from the lower value (small trapeziums) to the larger values (large trapezium)
167
+ for (let i of low_) if (shares[i] < lowThreshold[i]) return middleColors[i]
168
+ //else central color
169
+ return centerColor
170
+ }
171
+ fun.lowThreshold = lowThreshold
172
+ fun.highThreshold = highThreshold
173
+ fun.colors = colors
174
+ fun.middleColors = middleColors
175
+ fun.centerColor = centerColor
176
+ fun.lowIndex = low_
177
+ fun.highIndex = high_
178
+ return fun
179
+ }
180
+ */
181
+
182
+ /*
183
+ export const ternaryClassifier3 = (properties, totalFunction, opts = {}) => {
184
+ const [a01, a12, a20] = opts.thresholds || [1/3, 1/3, 1/3]
185
+ const [c0, c1, c2] = opts.colors || ["red", "green", "blue"]
186
+ const centerColor = opts.centerColor || "gray"
187
+
188
+ const fff = a => a == 1 ? Infinity : a / (1 - a)
189
+ const c01 = fff(a01), c12 = fff(a12), c20 = fff(a20)
190
+
191
+ const p0 = properties[0], p1 = properties[1], p2 = properties[2]
192
+ const fun = c => {
193
+ //get total
194
+ const tot = totalFunction(c)
195
+ if (!tot) return undefined
196
+ //compute shares
197
+ const [s0, s1, s2] = [+c[p0] / tot, +c[p1] / tot, +c[p2] / tot]
198
+ //return colors
199
+ if (s0 * c01 > s1 && s0 > s2 * c20) return c0
200
+ else if (s1 > s0 * c01 && s1 * c12 > s2) return c1
201
+ else if (s2 * c20 > s0 && s2 > s1 * c12) return c2
202
+ else return centerColor
203
+ }
204
+ fun.colors = [c0, c1, c2]
205
+ fun.centerColor = centerColor
206
+ return fun
207
+ }
208
+ */
@@ -1,58 +1,58 @@
1
- //@ts-check
2
- 'use strict'
3
-
4
- /**
5
- * Get the class id from a value and class break values
6
- *
7
- * @param {number} v the value
8
- * @param {Array.<number>} breaks the breaks
9
- * @returns The class id, from 0 to breaks.length
10
- * @deprecated use getClassifier instead.
11
- */
12
- export function getClass(v, breaks) {
13
- if (!breaks) return
14
- if (breaks.length == 0) return 0
15
- if (v <= breaks[0]) return 0
16
- for (let i = 1; i < breaks.length; i++) if (breaks[i - 1] < v && v <= breaks[i]) return i
17
- return breaks.length
18
- }
19
-
20
- //take 'nice' value (power of ten, or multiple)
21
- export function nice(v, multiples = [8, 6, 5, 4, 2.5, 2]) {
22
- //compute bigger power of ten below
23
- const v_ = Math.pow(10, Math.floor(Math.log10(v)))
24
- for (let multiple of multiples) if (v_ * multiple <= v) return v_ * multiple
25
- return v_
26
- }
27
-
28
- /*
29
- //no longer used
30
- export function loadImage(src) {
31
- return new Promise((resolve, reject) => {
32
- const img = new Image();
33
- img.onload = function () { resolve(img); };
34
- img.onerror = function () { reject(new Error('Error loading image')); };
35
- img.src = src;
36
- });
37
- }
38
- */
39
-
40
- /*
41
- export let monitor = false
42
-
43
- let previousDate
44
- export function monitorDuration(message) {
45
- const nowDate = Date.now()
46
-
47
- //first call
48
- if (!previousDate) {
49
- previousDate = nowDate
50
- console.log(previousDate, message)
51
- return
52
- }
53
-
54
- const d = nowDate - previousDate
55
- previousDate = nowDate
56
- console.log(d, message)
57
- }
58
- */
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ /**
5
+ * Get the class id from a value and class break values
6
+ *
7
+ * @param {number} v the value
8
+ * @param {Array.<number>} breaks the breaks
9
+ * @returns The class id, from 0 to breaks.length
10
+ * @deprecated use getClassifier instead.
11
+ */
12
+ export function getClass(v, breaks) {
13
+ if (!breaks) return
14
+ if (breaks.length == 0) return 0
15
+ if (v <= breaks[0]) return 0
16
+ for (let i = 1; i < breaks.length; i++) if (breaks[i - 1] < v && v <= breaks[i]) return i
17
+ return breaks.length
18
+ }
19
+
20
+ //take 'nice' value (power of ten, or multiple)
21
+ export function nice(v, multiples = [8, 6, 5, 4, 2.5, 2]) {
22
+ //compute bigger power of ten below
23
+ const v_ = Math.pow(10, Math.floor(Math.log10(v)))
24
+ for (let multiple of multiples) if (v_ * multiple <= v) return v_ * multiple
25
+ return v_
26
+ }
27
+
28
+ /*
29
+ //no longer used
30
+ export function loadImage(src) {
31
+ return new Promise((resolve, reject) => {
32
+ const img = new Image();
33
+ img.onload = function () { resolve(img); };
34
+ img.onerror = function () { reject(new Error('Error loading image')); };
35
+ img.src = src;
36
+ });
37
+ }
38
+ */
39
+
40
+ /*
41
+ export let monitor = false
42
+
43
+ let previousDate
44
+ export function monitorDuration(message) {
45
+ const nowDate = Date.now()
46
+
47
+ //first call
48
+ if (!previousDate) {
49
+ previousDate = nowDate
50
+ console.log(previousDate, message)
51
+ return
52
+ }
53
+
54
+ const d = nowDate - previousDate
55
+ previousDate = nowDate
56
+ console.log(d, message)
57
+ }
58
+ */