gridviz 2.0.40 → 2.0.42

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 +119 -119
  2. package/dist/gridviz.js +15722 -33305
  3. package/dist/gridviz.min.js +2 -2
  4. package/package.json +76 -77
  5. package/src/App.js +642 -698
  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 +101 -103
  10. package/src/GeoCanvas.js +420 -419
  11. package/src/LabelLayer.js +190 -190
  12. package/src/Layer.js +92 -92
  13. package/src/Legend.js +86 -86
  14. package/src/LineLayer.js +150 -150
  15. package/src/Style.js +114 -114
  16. package/src/Tooltip.js +168 -168
  17. package/src/dataset/COGeo.js +24 -24
  18. package/src/dataset/CSVGrid.js +104 -104
  19. package/src/dataset/GeoTIFF.js +127 -127
  20. package/src/dataset/GridTile.js +41 -41
  21. package/src/dataset/TiledGrid.js +264 -296
  22. package/src/index.js +176 -174
  23. package/src/legend/ColorCategoryLegend.js +124 -124
  24. package/src/legend/ColorDiscreteLegend.js +103 -105
  25. package/src/legend/ColorLegend.js +124 -125
  26. package/src/legend/SegmentOrientationLegend.js +87 -87
  27. package/src/legend/SegmentWidthLegend.js +97 -97
  28. package/src/legend/SizeLegend.js +141 -141
  29. package/src/style/CompositionStyle.js +300 -300
  30. package/src/style/ContourStyle.js +54 -54
  31. package/src/style/DotDensityStyle.js +156 -156
  32. package/src/style/JoyPlotStyle.js +135 -135
  33. package/src/style/LegoStyle.js +112 -112
  34. package/src/style/MosaicStyle.js +107 -107
  35. package/src/style/NinjaStarStyle.js +124 -124
  36. package/src/style/PillarStyle.js +230 -230
  37. package/src/style/SegmentStyle.js +142 -142
  38. package/src/style/ShapeColorSizeStyle.js +126 -126
  39. package/src/style/SideCatStyle.js +172 -172
  40. package/src/style/SideStyle.js +218 -218
  41. package/src/style/SquareColorCatWGLStyle.js +120 -120
  42. package/src/style/SquareColorWGLStyle.js +146 -146
  43. package/src/style/StrokeStyle.js +131 -131
  44. package/src/style/TanakaStyle.js +160 -160
  45. package/src/style/TextStyle.js +132 -132
  46. package/src/utils/Utils.js +35 -35
  47. package/src/utils/WebGLRectangleColoring.js +106 -106
  48. package/src/utils/WebGLSquareColoring.js +118 -118
  49. package/src/utils/WebGLSquareColoringAdvanced.js +230 -230
  50. package/src/utils/WebGLSquareColoringCatAdvanced.js +133 -133
  51. package/src/utils/WebGLSquareColoringKS.js +153 -153
  52. package/src/utils/stretching.js +131 -131
  53. package/src/utils/webGLUtils.js +71 -71
  54. package/src/utils/zoomUtils.js +142 -142
  55. package/src/dataset/ParquetGrid.js +0 -122
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,92 +1,92 @@
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,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
- /** The minimum zoom factor: Below this level, the layer is not shown.
29
- * @type {number} */
30
- this.minZoom = opts.minZoom || 0
31
-
32
- /** The maximum zoom factor: Above this level, the layer is not shown.
33
- * @type {number} */
34
- this.maxZoom = opts.maxZoom || Infinity
35
-
36
- //ensure acceptable values for the zoom limits.
37
- if (this.minZoom >= this.maxZoom)
38
- throw new Error('Unexpected zoom limits for layer. Zoom min should be smaller than zoom max.')
39
-
40
- /** Unit: number of pixels
41
- * @type {number} */
42
- this.pixNb = opts.pixNb || 3
43
-
44
- /**
45
- * The function returning cell information as HTML.
46
- * This is typically used for tooltip information.
47
- * @type {function(import("./Dataset").Cell, number):string} */
48
- this.cellInfoHTML = opts.cellInfoHTML || Layer.defaultCellInfoHTML
49
- }
50
-
51
- /**
52
- * Return the relevant dataset component for a specified zoom factor.
53
- *
54
- * @param {number} zf
55
- * @returns {import("./DatasetComponent").DatasetComponent|undefined}
56
- * */
57
- getDatasetComponent(zf) {
58
- if (zf < this.minZoom || zf > this.maxZoom) return
59
-
60
- //special case whith single component dataset
61
- if (this.dataset.datasetComponents.length == 1) return this.dataset.datasetComponents[0]
62
-
63
- const rs = this.dataset.resolutions
64
- let i = 0
65
- let z = rs[i] / this.pixNb
66
- while (z < zf && i < rs.length) {
67
- i++
68
- z = rs[i] / this.pixNb
69
- }
70
- //if (i == 0) return this.dataset.datasetComponents[0];
71
- //return this.dataset.datasetComponents[i - 1];
72
- if (i == rs.length) return this.dataset.datasetComponents[rs.length - 1]
73
- return this.dataset.datasetComponents[i]
74
- }
75
-
76
- /**
77
- * The default function returning cell information as HTML.
78
- * This is typically used for tooltip information.
79
- *
80
- * @param {import("./Dataset").Cell} cell
81
- * @returns {string}
82
- */
83
- static defaultCellInfoHTML(cell) {
84
- const buf = []
85
- for (const key of Object.keys(cell)) {
86
- if (key === 'x') continue
87
- if (key === 'y') continue
88
- buf.push('<b>', key, '</b>', ' : ', cell[key], '<br>')
89
- }
90
- return buf.join('')
91
- }
92
- }
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,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
+ /** The minimum zoom factor: Below this level, the layer is not shown.
29
+ * @type {number} */
30
+ this.minZoom = opts.minZoom || 0
31
+
32
+ /** The maximum zoom factor: Above this level, the layer is not shown.
33
+ * @type {number} */
34
+ this.maxZoom = opts.maxZoom || Infinity
35
+
36
+ //ensure acceptable values for the zoom limits.
37
+ if (this.minZoom >= this.maxZoom)
38
+ throw new Error('Unexpected zoom limits for layer. Zoom min should be smaller than zoom max.')
39
+
40
+ /** Unit: number of pixels
41
+ * @type {number} */
42
+ this.pixNb = opts.pixNb || 3
43
+
44
+ /**
45
+ * The function returning cell information as HTML.
46
+ * This is typically used for tooltip information.
47
+ * @type {function(import("./Dataset").Cell, number):string} */
48
+ this.cellInfoHTML = opts.cellInfoHTML || Layer.defaultCellInfoHTML
49
+ }
50
+
51
+ /**
52
+ * Return the relevant dataset component for a specified zoom factor.
53
+ *
54
+ * @param {number} zf
55
+ * @returns {import("./DatasetComponent").DatasetComponent|undefined}
56
+ * */
57
+ getDatasetComponent(zf) {
58
+ if (zf < this.minZoom || zf > this.maxZoom) return
59
+
60
+ //special case whith single component dataset
61
+ if (this.dataset.datasetComponents.length == 1) return this.dataset.datasetComponents[0]
62
+
63
+ const rs = this.dataset.resolutions
64
+ let i = 0
65
+ let z = rs[i] / this.pixNb
66
+ while (z < zf && i < rs.length) {
67
+ i++
68
+ z = rs[i] / this.pixNb
69
+ }
70
+ //if (i == 0) return this.dataset.datasetComponents[0];
71
+ //return this.dataset.datasetComponents[i - 1];
72
+ if (i == rs.length) return this.dataset.datasetComponents[rs.length - 1]
73
+ return this.dataset.datasetComponents[i]
74
+ }
75
+
76
+ /**
77
+ * The default function returning cell information as HTML.
78
+ * This is typically used for tooltip information.
79
+ *
80
+ * @param {import("./Dataset").Cell} cell
81
+ * @returns {string}
82
+ */
83
+ static defaultCellInfoHTML(cell) {
84
+ const buf = []
85
+ for (const key of Object.keys(cell)) {
86
+ if (key === 'x') continue
87
+ if (key === 'y') continue
88
+ buf.push('<b>', key, '</b>', ' : ', cell[key], '<br>')
89
+ }
90
+ return buf.join('')
91
+ }
92
+ }