gridviz 2.1.12 → 2.1.13

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 (60) hide show
  1. package/README.md +125 -125
  2. package/dist/gridviz.js +8249 -7909
  3. package/dist/gridviz.min.js +1 -1
  4. package/package.json +77 -77
  5. package/src/App.js +758 -705
  6. package/src/BackgroundLayer.js +182 -182
  7. package/src/BackgroundLayerWMS.js +131 -131
  8. package/src/Dataset.js +76 -76
  9. package/src/DatasetComponent.js +113 -113
  10. package/src/GeoCanvas.js +420 -420
  11. package/src/LabelLayer.js +190 -190
  12. package/src/Layer.js +103 -103
  13. package/src/Legend.js +86 -86
  14. package/src/LineLayer.js +150 -150
  15. package/src/Style.js +129 -129
  16. package/src/Tooltip.js +180 -180
  17. package/src/button/Button.js +54 -0
  18. package/src/button/FullscreenButton.js +98 -0
  19. package/src/button/ZoomButtons.js +72 -0
  20. package/src/dataset/COGeo.js +24 -24
  21. package/src/dataset/CSVGrid.js +104 -104
  22. package/src/dataset/GeoTIFF.js +127 -127
  23. package/src/dataset/GridTile.js +41 -41
  24. package/src/dataset/LGrid.js +54 -54
  25. package/src/dataset/TiledGrid.js +264 -264
  26. package/src/index.js +71 -71
  27. package/src/legend/ColorCategoryLegend.js +124 -124
  28. package/src/legend/ColorDiscreteLegend.js +103 -103
  29. package/src/legend/ColorLegend.js +128 -124
  30. package/src/legend/SegmentOrientationLegend.js +87 -87
  31. package/src/legend/SegmentWidthLegend.js +101 -97
  32. package/src/legend/SizeLegend.js +141 -141
  33. package/src/style/CompositionStyle.js +300 -300
  34. package/src/style/ContourStyle.js +54 -54
  35. package/src/style/DotDensityStyle.js +156 -156
  36. package/src/style/IsoFenceStyle.js +262 -262
  37. package/src/style/JoyPlotStyle.js +135 -135
  38. package/src/style/LegoStyle.js +112 -112
  39. package/src/style/MosaicStyle.js +107 -107
  40. package/src/style/NinjaStarStyle.js +125 -125
  41. package/src/style/PillarStyle.js +230 -230
  42. package/src/style/SegmentStyle.js +142 -142
  43. package/src/style/ShapeColorSizeStyle.js +152 -152
  44. package/src/style/SideCatStyle.js +172 -172
  45. package/src/style/SideStyle.js +216 -216
  46. package/src/style/SquareColorCatWGLStyle.js +120 -120
  47. package/src/style/SquareColorWGLStyle.js +146 -146
  48. package/src/style/StrokeStyle.js +131 -131
  49. package/src/style/TanakaStyle.js +160 -160
  50. package/src/style/TextStyle.js +132 -132
  51. package/src/style/TimeSeriesStyle.js +259 -250
  52. package/src/utils/Utils.js +35 -35
  53. package/src/utils/WebGLRectangleColoring.js +106 -106
  54. package/src/utils/WebGLSquareColoring.js +118 -118
  55. package/src/utils/WebGLSquareColoringAdvanced.js +230 -230
  56. package/src/utils/WebGLSquareColoringCatAdvanced.js +133 -133
  57. package/src/utils/WebGLSquareColoringKS.js +153 -153
  58. package/src/utils/stretching.js +131 -131
  59. package/src/utils/webGLUtils.js +71 -71
  60. package/src/utils/zoomUtils.js +142 -142
package/src/LabelLayer.js CHANGED
@@ -1,190 +1,190 @@
1
- //@ts-check
2
- 'use strict'
3
-
4
- import { csv } from 'd3-fetch'
5
-
6
- /** A label. The name is the text to show. (x,y) are the coordinates in the same CRS as the grid.
7
- * @typedef {{name: string, x:number, y:number }} Label */
8
-
9
- /**
10
- * A (generic) layer for placename labels, to be shown on top of the grid layers.
11
- * The input is a CSV file with the position (x, y) of the labels and name + some other info on the label importance.
12
- * If the label data is not in the expected format or in the same CRS as the grid, it can be corrected with the "preprocess" function.
13
- * The selection of the label, their style (font, weight, etc.) and color can be specified depending on their importance and the zoom level.
14
- *
15
- * @author Joseph Davies, Julien Gaffuri
16
- */
17
- export class LabelLayer {
18
- /**
19
- * @param {object} opts
20
- */
21
- constructor(opts) {
22
- opts = opts || {}
23
-
24
- /**
25
- * The URL of the label data, as CSV file.
26
- * The file should contain the information for each label such as the text, the position and other information for the display of the label according to the zoom level.
27
- * If necessary, this data can be reformated with the 'preprocess' parameter.
28
- * @private
29
- * @type {string} */
30
- this.url = opts.url
31
-
32
- /** Specify if and how a label should be drawn, depending on its importance and the zoom level.
33
- * @private
34
- * @type {function(Label,number):string} */
35
- this.style = opts.style || (() => 'bold 1em Arial')
36
-
37
- /** Specify the label color, depending on its importance and the zoom level.
38
- * @private
39
- * @type {function(Label,number):string} */
40
- this.color = opts.color || (opts.dark ? () => '#ddd' : () => '#222')
41
-
42
- /** Specify the label halo color, depending on its importance and the zoom level.
43
- * @private
44
- * @type {function(Label,number):string} */
45
- this.haloColor = opts.haloColor || (opts.dark ? () => '#000000BB' : () => '#FFFFFFBB')
46
-
47
- /** Specify the label halo width, depending on its importance and the zoom level.
48
- * @private
49
- * @type {function(Label,number):number} */
50
- this.haloWidth = opts.haloWidth || (() => 4)
51
-
52
- /** The anchor where to draw the text, from label position. See HTML-canvas textAlign property.
53
- * "left" || "right" || "center" || "start" || "end"
54
- * @private
55
- * @type {CanvasTextAlign} */
56
- this.textAlign = opts.textAlign || 'start'
57
-
58
- /**
59
- * @private
60
- * @type {Array.<number>} */
61
- this.offsetPix = opts.offsetPix || [5, 5]
62
-
63
- /**
64
- * A preprocess to run on each label after loading.
65
- * It can be used to apply some specific treatment before, format the label data, project coordinates, etc.
66
- * Return false if the label should not be kept.
67
- * @private
68
- * @type {function(Label):boolean} */
69
- this.preprocess = opts.preprocess
70
-
71
- /**
72
- * @private
73
- * @type {Array.<Label> | undefined} */
74
- this.labels = undefined
75
-
76
- /**
77
- * @private
78
- * @type {string} */
79
- this.loadingStatus = 'notLoaded'
80
- }
81
-
82
- /**
83
- * Draw the label layer.
84
- *
85
- * @param {import("./GeoCanvas").GeoCanvas} cg The canvas where to draw the layer.
86
- * @returns {void}
87
- */
88
- draw(cg) {
89
- //load labels, if not done yet.
90
- if (!this.labels) {
91
- this.load(cg.redraw)
92
- return
93
- }
94
-
95
- //zoom factor
96
- const zf = cg.getZf()
97
-
98
- //text align
99
- cg.ctx.textAlign = this.textAlign || 'start'
100
-
101
- //line join and cap
102
- cg.ctx.lineJoin = 'bevel' //|| "round" || "miter";
103
- cg.ctx.lineCap = 'butt' //|| "round" || "square";
104
-
105
- //draw in pix coordinates
106
- cg.initCanvasTransform()
107
-
108
- //draw labels, one by one
109
- for (const lb of this.labels) {
110
- //get label style
111
- const st = this.style(lb, zf)
112
- if (!st) continue
113
- cg.ctx.font = st
114
-
115
- //check label within the view, to be drawn
116
- if (!cg.toDraw(lb)) continue
117
-
118
- //position
119
- const xP = cg.geoToPixX(lb.x) + this.offsetPix[0]
120
- const yP = cg.geoToPixY(lb.y) - this.offsetPix[1]
121
-
122
- //label stroke, for the halo
123
- if (this.haloColor && this.haloWidth) {
124
- const hc = this.haloColor(lb, zf)
125
- const hw = this.haloWidth(lb, zf)
126
- if (hc && hw && hw > 0) {
127
- cg.ctx.strokeStyle = hc
128
- cg.ctx.lineWidth = hw
129
- cg.ctx.strokeText(lb.name, xP, yP)
130
- }
131
- }
132
-
133
- //label fill
134
- if (this.color) {
135
- const col = this.color(lb, zf)
136
- if (col) {
137
- cg.ctx.fillStyle = col
138
- cg.ctx.fillText(lb.name, xP, yP)
139
- }
140
- }
141
- }
142
- }
143
-
144
- /**
145
- * Load data for labels, from URL this.url
146
- * @param {function():void} callback
147
- * @private
148
- */
149
- async load(callback) {
150
- if (!this.url) {
151
- console.log('Failed loading labels: No URL specified. ' + this.url)
152
- this.loadingStatus = 'failed'
153
- this.labels = []
154
- return
155
- }
156
-
157
- //check if data already loaded
158
- if (this.loadingStatus != 'notLoaded') return
159
-
160
- //load data
161
- this.loadingStatus = 'loading'
162
-
163
- try {
164
- /** @type { Array.<Label> } */
165
- const data = await csv(this.url)
166
-
167
- //preprocess/filter
168
- if (this.preprocess) {
169
- this.labels = []
170
- for (const c of data) {
171
- const b = this.preprocess(c)
172
- if (b == false) continue
173
- this.labels.push(c)
174
- }
175
- } else {
176
- //store labels
177
- this.labels = data
178
- }
179
-
180
- this.loadingStatus = 'loaded'
181
-
182
- //redraw
183
- if (callback) callback()
184
- } catch (error) {
185
- console.log('Failed loading labels from ' + this.url)
186
- this.labels = []
187
- this.loadingStatus = 'failed'
188
- }
189
- }
190
- }
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ import { csv } from 'd3-fetch'
5
+
6
+ /** A label. The name is the text to show. (x,y) are the coordinates in the same CRS as the grid.
7
+ * @typedef {{name: string, x:number, y:number }} Label */
8
+
9
+ /**
10
+ * A (generic) layer for placename labels, to be shown on top of the grid layers.
11
+ * The input is a CSV file with the position (x, y) of the labels and name + some other info on the label importance.
12
+ * If the label data is not in the expected format or in the same CRS as the grid, it can be corrected with the "preprocess" function.
13
+ * The selection of the label, their style (font, weight, etc.) and color can be specified depending on their importance and the zoom level.
14
+ *
15
+ * @author Joseph Davies, Julien Gaffuri
16
+ */
17
+ export class LabelLayer {
18
+ /**
19
+ * @param {object} opts
20
+ */
21
+ constructor(opts) {
22
+ opts = opts || {}
23
+
24
+ /**
25
+ * The URL of the label data, as CSV file.
26
+ * The file should contain the information for each label such as the text, the position and other information for the display of the label according to the zoom level.
27
+ * If necessary, this data can be reformated with the 'preprocess' parameter.
28
+ * @private
29
+ * @type {string} */
30
+ this.url = opts.url
31
+
32
+ /** Specify if and how a label should be drawn, depending on its importance and the zoom level.
33
+ * @private
34
+ * @type {function(Label,number):string} */
35
+ this.style = opts.style || (() => 'bold 1em Arial')
36
+
37
+ /** Specify the label color, depending on its importance and the zoom level.
38
+ * @private
39
+ * @type {function(Label,number):string} */
40
+ this.color = opts.color || (opts.dark ? () => '#ddd' : () => '#222')
41
+
42
+ /** Specify the label halo color, depending on its importance and the zoom level.
43
+ * @private
44
+ * @type {function(Label,number):string} */
45
+ this.haloColor = opts.haloColor || (opts.dark ? () => '#000000BB' : () => '#FFFFFFBB')
46
+
47
+ /** Specify the label halo width, depending on its importance and the zoom level.
48
+ * @private
49
+ * @type {function(Label,number):number} */
50
+ this.haloWidth = opts.haloWidth || (() => 4)
51
+
52
+ /** The anchor where to draw the text, from label position. See HTML-canvas textAlign property.
53
+ * "left" || "right" || "center" || "start" || "end"
54
+ * @private
55
+ * @type {CanvasTextAlign} */
56
+ this.textAlign = opts.textAlign || 'start'
57
+
58
+ /**
59
+ * @private
60
+ * @type {Array.<number>} */
61
+ this.offsetPix = opts.offsetPix || [5, 5]
62
+
63
+ /**
64
+ * A preprocess to run on each label after loading.
65
+ * It can be used to apply some specific treatment before, format the label data, project coordinates, etc.
66
+ * Return false if the label should not be kept.
67
+ * @private
68
+ * @type {function(Label):boolean} */
69
+ this.preprocess = opts.preprocess
70
+
71
+ /**
72
+ * @private
73
+ * @type {Array.<Label> | undefined} */
74
+ this.labels = undefined
75
+
76
+ /**
77
+ * @private
78
+ * @type {string} */
79
+ this.loadingStatus = 'notLoaded'
80
+ }
81
+
82
+ /**
83
+ * Draw the label layer.
84
+ *
85
+ * @param {import("./GeoCanvas").GeoCanvas} cg The canvas where to draw the layer.
86
+ * @returns {void}
87
+ */
88
+ draw(cg) {
89
+ //load labels, if not done yet.
90
+ if (!this.labels) {
91
+ this.load(cg.redraw)
92
+ return
93
+ }
94
+
95
+ //zoom factor
96
+ const zf = cg.getZf()
97
+
98
+ //text align
99
+ cg.ctx.textAlign = this.textAlign || 'start'
100
+
101
+ //line join and cap
102
+ cg.ctx.lineJoin = 'bevel' //|| "round" || "miter";
103
+ cg.ctx.lineCap = 'butt' //|| "round" || "square";
104
+
105
+ //draw in pix coordinates
106
+ cg.initCanvasTransform()
107
+
108
+ //draw labels, one by one
109
+ for (const lb of this.labels) {
110
+ //get label style
111
+ const st = this.style(lb, zf)
112
+ if (!st) continue
113
+ cg.ctx.font = st
114
+
115
+ //check label within the view, to be drawn
116
+ if (!cg.toDraw(lb)) continue
117
+
118
+ //position
119
+ const xP = cg.geoToPixX(lb.x) + this.offsetPix[0]
120
+ const yP = cg.geoToPixY(lb.y) - this.offsetPix[1]
121
+
122
+ //label stroke, for the halo
123
+ if (this.haloColor && this.haloWidth) {
124
+ const hc = this.haloColor(lb, zf)
125
+ const hw = this.haloWidth(lb, zf)
126
+ if (hc && hw && hw > 0) {
127
+ cg.ctx.strokeStyle = hc
128
+ cg.ctx.lineWidth = hw
129
+ cg.ctx.strokeText(lb.name, xP, yP)
130
+ }
131
+ }
132
+
133
+ //label fill
134
+ if (this.color) {
135
+ const col = this.color(lb, zf)
136
+ if (col) {
137
+ cg.ctx.fillStyle = col
138
+ cg.ctx.fillText(lb.name, xP, yP)
139
+ }
140
+ }
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Load data for labels, from URL this.url
146
+ * @param {function():void} callback
147
+ * @private
148
+ */
149
+ async load(callback) {
150
+ if (!this.url) {
151
+ console.log('Failed loading labels: No URL specified. ' + this.url)
152
+ this.loadingStatus = 'failed'
153
+ this.labels = []
154
+ return
155
+ }
156
+
157
+ //check if data already loaded
158
+ if (this.loadingStatus != 'notLoaded') return
159
+
160
+ //load data
161
+ this.loadingStatus = 'loading'
162
+
163
+ try {
164
+ /** @type { Array.<Label> } */
165
+ const data = await csv(this.url)
166
+
167
+ //preprocess/filter
168
+ if (this.preprocess) {
169
+ this.labels = []
170
+ for (const c of data) {
171
+ const b = this.preprocess(c)
172
+ if (b == false) continue
173
+ this.labels.push(c)
174
+ }
175
+ } else {
176
+ //store labels
177
+ this.labels = data
178
+ }
179
+
180
+ this.loadingStatus = 'loaded'
181
+
182
+ //redraw
183
+ if (callback) callback()
184
+ } catch (error) {
185
+ console.log('Failed loading labels from ' + this.url)
186
+ this.labels = []
187
+ this.loadingStatus = 'failed'
188
+ }
189
+ }
190
+ }
package/src/Layer.js CHANGED
@@ -1,103 +1,103 @@
1
- //@ts-check
2
- 'use strict'
3
-
4
- /**
5
- * A layer, which specifies a dataset to be shown with specified styles.
6
- *
7
- * @author Joseph Davies, Julien Gaffuri
8
- */
9
- export class Layer {
10
- /**
11
- * @param {import("./Dataset").Dataset} dataset The multi resolution dataset to show.
12
- * @param {Array.<import("./Style").Style>} styles The styles, ordered in drawing order.
13
- * @param {{visible?:boolean,alpha?:number,blendOperation?:GlobalCompositeOperation,minZoom?:number,maxZoom?:number,pixNb?:number,cellInfoHTML?:function(import("./Dataset").Cell):string}} opts
14
- * minZoom: The minimum zoom level when to show the layer. maxZoom: The maximum zoom level when to show the layer
15
- */
16
- constructor(dataset, styles, opts = {}) {
17
- opts = opts || {}
18
-
19
- /** @type {import("./Dataset").Dataset} */
20
- this.dataset = dataset
21
- /** @type {Array.<import("./Style").Style>} */
22
- this.styles = styles
23
-
24
- /** An attribute to specify if a layer should be drawn or not
25
- * @type {boolean} */
26
- this.visible = opts.visible === false ? false : true
27
-
28
- /** A function returning the alpha (transparency/opacity), between 0.0 (fully transparent) and 1.0 (fully opaque).
29
- * The function parameter is the zoom factor.
30
- * (see CanvasRenderingContext2D: globalAlpha property)
31
- * @type {function(number):number|undefined} */
32
- this.alpha = opts.alpha
33
-
34
- /** A function returning the blend operation. The function parameter is the zoom factor.
35
- * (see CanvasRenderingContext2D: globalCompositeOperation property)
36
- * @type {GlobalCompositeOperation} */
37
- this.blendOperation = opts.blendOperation || (zf => "source-over")
38
-
39
- /** The minimum zoom factor: Below this level, the layer is not shown.
40
- * @type {number} */
41
- this.minZoom = opts.minZoom || 0
42
-
43
- /** The maximum zoom factor: Above this level, the layer is not shown.
44
- * @type {number} */
45
- this.maxZoom = opts.maxZoom || Infinity
46
-
47
- //ensure acceptable values for the zoom limits.
48
- if (this.minZoom >= this.maxZoom)
49
- throw new Error('Unexpected zoom limits for layer. Zoom min should be smaller than zoom max.')
50
-
51
- /** Unit: number of pixels
52
- * @type {number} */
53
- this.pixNb = opts.pixNb || 3
54
-
55
- /**
56
- * The function returning cell information as HTML.
57
- * This is typically used for tooltip information.
58
- * @type {function(import("./Dataset").Cell, number):string} */
59
- this.cellInfoHTML = opts.cellInfoHTML || Layer.defaultCellInfoHTML
60
- }
61
-
62
- /**
63
- * Return the relevant dataset component for a specified zoom factor.
64
- *
65
- * @param {number} zf
66
- * @returns {import("./DatasetComponent").DatasetComponent|undefined}
67
- * */
68
- getDatasetComponent(zf) {
69
- if (zf < this.minZoom || zf > this.maxZoom) return
70
-
71
- //special case whith single component dataset
72
- if (this.dataset.datasetComponents.length == 1) return this.dataset.datasetComponents[0]
73
-
74
- const rs = this.dataset.resolutions
75
- let i = 0
76
- let z = rs[i] / this.pixNb
77
- while (z < zf && i < rs.length) {
78
- i++
79
- z = rs[i] / this.pixNb
80
- }
81
- //if (i == 0) return this.dataset.datasetComponents[0];
82
- //return this.dataset.datasetComponents[i - 1];
83
- if (i == rs.length) return this.dataset.datasetComponents[rs.length - 1]
84
- return this.dataset.datasetComponents[i]
85
- }
86
-
87
- /**
88
- * The default function returning cell information as HTML.
89
- * This is typically used for tooltip information.
90
- *
91
- * @param {import("./Dataset").Cell} cell
92
- * @returns {string}
93
- */
94
- static defaultCellInfoHTML(cell) {
95
- const buf = []
96
- for (const key of Object.keys(cell)) {
97
- if (key === 'x') continue
98
- if (key === 'y') continue
99
- buf.push('<b>', key, '</b>', ' : ', cell[key], '<br>')
100
- }
101
- return buf.join('')
102
- }
103
- }
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ /**
5
+ * A layer, which specifies a dataset to be shown with specified styles.
6
+ *
7
+ * @author Joseph Davies, Julien Gaffuri
8
+ */
9
+ export class Layer {
10
+ /**
11
+ * @param {import("./Dataset").Dataset} dataset The multi resolution dataset to show.
12
+ * @param {Array.<import("./Style").Style>} styles The styles, ordered in drawing order.
13
+ * @param {{visible?:boolean,alpha?:number,blendOperation?:GlobalCompositeOperation,minZoom?:number,maxZoom?:number,pixNb?:number,cellInfoHTML?:function(import("./Dataset").Cell):string}} opts
14
+ * minZoom: The minimum zoom level when to show the layer. maxZoom: The maximum zoom level when to show the layer
15
+ */
16
+ constructor(dataset, styles, opts = {}) {
17
+ opts = opts || {}
18
+
19
+ /** @type {import("./Dataset").Dataset} */
20
+ this.dataset = dataset
21
+ /** @type {Array.<import("./Style").Style>} */
22
+ this.styles = styles
23
+
24
+ /** An attribute to specify if a layer should be drawn or not
25
+ * @type {boolean} */
26
+ this.visible = opts.visible === false ? false : true
27
+
28
+ /** A function returning the alpha (transparency/opacity), between 0.0 (fully transparent) and 1.0 (fully opaque).
29
+ * The function parameter is the zoom factor.
30
+ * (see CanvasRenderingContext2D: globalAlpha property)
31
+ * @type {function(number):number|undefined} */
32
+ this.alpha = opts.alpha
33
+
34
+ /** A function returning the blend operation. The function parameter is the zoom factor.
35
+ * (see CanvasRenderingContext2D: globalCompositeOperation property)
36
+ * @type {GlobalCompositeOperation} */
37
+ this.blendOperation = opts.blendOperation || (zf => "source-over")
38
+
39
+ /** The minimum zoom factor: Below this level, the layer is not shown.
40
+ * @type {number} */
41
+ this.minZoom = opts.minZoom || 0
42
+
43
+ /** The maximum zoom factor: Above this level, the layer is not shown.
44
+ * @type {number} */
45
+ this.maxZoom = opts.maxZoom || Infinity
46
+
47
+ //ensure acceptable values for the zoom limits.
48
+ if (this.minZoom >= this.maxZoom)
49
+ throw new Error('Unexpected zoom limits for layer. Zoom min should be smaller than zoom max.')
50
+
51
+ /** Unit: number of pixels
52
+ * @type {number} */
53
+ this.pixNb = opts.pixNb || 3
54
+
55
+ /**
56
+ * The function returning cell information as HTML.
57
+ * This is typically used for tooltip information.
58
+ * @type {function(import("./Dataset").Cell, number):string} */
59
+ this.cellInfoHTML = opts.cellInfoHTML || Layer.defaultCellInfoHTML
60
+ }
61
+
62
+ /**
63
+ * Return the relevant dataset component for a specified zoom factor.
64
+ *
65
+ * @param {number} zf
66
+ * @returns {import("./DatasetComponent").DatasetComponent|undefined}
67
+ * */
68
+ getDatasetComponent(zf) {
69
+ if (zf < this.minZoom || zf > this.maxZoom) return
70
+
71
+ //special case whith single component dataset
72
+ if (this.dataset.datasetComponents.length == 1) return this.dataset.datasetComponents[0]
73
+
74
+ const rs = this.dataset.resolutions
75
+ let i = 0
76
+ let z = rs[i] / this.pixNb
77
+ while (z < zf && i < rs.length) {
78
+ i++
79
+ z = rs[i] / this.pixNb
80
+ }
81
+ //if (i == 0) return this.dataset.datasetComponents[0];
82
+ //return this.dataset.datasetComponents[i - 1];
83
+ if (i == rs.length) return this.dataset.datasetComponents[rs.length - 1]
84
+ return this.dataset.datasetComponents[i]
85
+ }
86
+
87
+ /**
88
+ * The default function returning cell information as HTML.
89
+ * This is typically used for tooltip information.
90
+ *
91
+ * @param {import("./Dataset").Cell} cell
92
+ * @returns {string}
93
+ */
94
+ static defaultCellInfoHTML(cell) {
95
+ const buf = []
96
+ for (const key of Object.keys(cell)) {
97
+ if (key === 'x') continue
98
+ if (key === 'y') continue
99
+ buf.push('<b>', key, '</b>', ' : ', cell[key], '<br>')
100
+ }
101
+ return buf.join('')
102
+ }
103
+ }