gridviz 3.0.18 → 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 (56) hide show
  1. package/README.md +128 -127
  2. package/dist/gridviz.js +7862 -7819
  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 -419
  9. package/src/core/Layer.js +23 -23
  10. package/src/core/Legend.js +108 -108
  11. package/src/core/Map.js +516 -503
  12. package/src/core/MultiResolutionDataset.js +93 -93
  13. package/src/core/Style.js +98 -98
  14. package/src/core/Tooltip.js +1 -0
  15. package/src/dataset/CSVGrid.js +112 -112
  16. package/src/dataset/GeoTIFF.js +122 -122
  17. package/src/dataset/JSGrid.js +55 -55
  18. package/src/dataset/TiledGrid.js +302 -289
  19. package/src/dataset/worker.js +18 -18
  20. package/src/index.js +77 -77
  21. package/src/layer/BackgroundLayer.js +162 -162
  22. package/src/layer/BackgroundLayerImage.js +81 -81
  23. package/src/layer/BackgroundLayerWMS.js +104 -104
  24. package/src/layer/GeoJSONLayer.js +214 -214
  25. package/src/layer/GridLayer.js +148 -148
  26. package/src/layer/LabelLayer.js +194 -194
  27. package/src/legend/ColorCategoryLegend.js +109 -109
  28. package/src/legend/ColorDiscreteLegend.js +100 -100
  29. package/src/legend/ColorLegend.js +115 -115
  30. package/src/legend/OrientationLegend.js +89 -89
  31. package/src/legend/SizeLegend.js +224 -224
  32. package/src/legend/TernaryLegend.js +302 -302
  33. package/src/style/CompositionStyle.js +291 -291
  34. package/src/style/DotDensityStyle.js +133 -133
  35. package/src/style/ImageStyle.js +100 -100
  36. package/src/style/IsoFenceStyle.js +217 -217
  37. package/src/style/JoyPlotStyle.js +127 -127
  38. package/src/style/LegoStyle.js +110 -110
  39. package/src/style/MosaicStyle.js +99 -99
  40. package/src/style/NinjaStarStyle.js +102 -102
  41. package/src/style/PillarStyle.js +207 -207
  42. package/src/style/SegmentStyle.js +105 -105
  43. package/src/style/ShapeColorSizeStyle.js +147 -147
  44. package/src/style/SideCategoryStyle.js +112 -112
  45. package/src/style/SideStyle.js +212 -212
  46. package/src/style/SquareColorCategoryWebGLStyle.js +107 -107
  47. package/src/style/SquareColorWebGLStyle.js +126 -126
  48. package/src/style/StrokeStyle.js +135 -135
  49. package/src/style/TanakaStyle.js +69 -69
  50. package/src/style/TextStyle.js +110 -110
  51. package/src/style/TimeSeriesStyle.js +222 -222
  52. package/src/utils/scale.js +218 -218
  53. package/src/utils/stretching.js +120 -120
  54. package/src/utils/ternary.js +208 -203
  55. package/src/utils/utils.js +58 -58
  56. package/src/utils/webGLUtils.js +72 -72
@@ -1,203 +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
- //paramerter 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
- const orderedIndexesDec = arr => [...arr.keys()].sort((a, b) => arr[b] - arr[a]);
135
- const orderedIndexesInc = arr => [...arr.keys()].sort((a, b) => arr[a] - arr[b]);
136
-
137
- export const ternaryClassifier = (properties, totalFunction, opts = {}) => {
138
- const lowThreshold = opts.lowThreshold || [1 / 3, 1 / 3, 1 / 3]
139
- const highThreshold = opts.highThreshold || [2 / 3, 2 / 3, 2 / 3]
140
- const colors = opts.colors || ["red", "green", "blue"]
141
- const colorInterpolation = opts.colorInterpolation || interpolateLab
142
-
143
- //https://d3js.org/d3-interpolate/color
144
- const middleColorFunction = (color1, color2) => colorInterpolation(color1, color2)(0.5)
145
- const middleColors = opts.middleColors || [middleColorFunction(colors[1], colors[2]), middleColorFunction(colors[0], colors[2]), middleColorFunction(colors[0], colors[1])]
146
- const centerColor = opts.centerColor || colorInterpolation(middleColors[2], colors[2])(0.333)
147
-
148
- const high_ = orderedIndexesDec(highThreshold)
149
- const low_ = orderedIndexesInc(lowThreshold)
150
-
151
- const p0 = properties[0], p1 = properties[1], p2 = properties[2]
152
- const fun = c => {
153
- //get total
154
- const tot = totalFunction(c)
155
- if (!tot) return undefined
156
- //compute shares
157
- const shares = [+c[p0] / tot, +c[p1] / tot, +c[p2] / tot]
158
- //return colors
159
- //start first with the extreme high (triangles): from the larger value (small triangle) to the lower value (large triangle)
160
- for (let i of high_) if (shares[i] > highThreshold[i]) return colors[i]
161
- //then draw the extreme low (trapeziums): from the lower value (small trapeziums) to the larger values (large trapezium)
162
- for (let i of low_) if (shares[i] < lowThreshold[i]) return middleColors[i]
163
- //else central color
164
- return centerColor
165
- }
166
- fun.lowThreshold = lowThreshold
167
- fun.highThreshold = highThreshold
168
- fun.colors = colors
169
- fun.middleColors = middleColors
170
- fun.centerColor = centerColor
171
- fun.lowIndex = low_
172
- fun.highIndex = high_
173
- return fun
174
- }
175
- */
176
-
177
- /*
178
- export const ternaryClassifier3 = (properties, totalFunction, opts = {}) => {
179
- const [a01, a12, a20] = opts.thresholds || [1/3, 1/3, 1/3]
180
- const [c0, c1, c2] = opts.colors || ["red", "green", "blue"]
181
- const centerColor = opts.centerColor || "gray"
182
-
183
- const fff = a => a == 1 ? Infinity : a / (1 - a)
184
- const c01 = fff(a01), c12 = fff(a12), c20 = fff(a20)
185
-
186
- const p0 = properties[0], p1 = properties[1], p2 = properties[2]
187
- const fun = c => {
188
- //get total
189
- const tot = totalFunction(c)
190
- if (!tot) return undefined
191
- //compute shares
192
- const [s0, s1, s2] = [+c[p0] / tot, +c[p1] / tot, +c[p2] / tot]
193
- //return colors
194
- if (s0 * c01 > s1 && s0 > s2 * c20) return c0
195
- else if (s1 > s0 * c01 && s1 * c12 > s2) return c1
196
- else if (s2 * c20 > s0 && s2 > s1 * c12) return c2
197
- else return centerColor
198
- }
199
- fun.colors = [c0, c1, c2]
200
- fun.centerColor = centerColor
201
- return fun
202
- }
203
- */
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
+ */