gridviz 3.0.34 → 3.0.36

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 (67) hide show
  1. package/README.md +129 -129
  2. package/dist/gridviz.js +17487 -17471
  3. package/dist/gridviz.min.js +2 -2
  4. package/package.json +73 -73
  5. package/src/button/Button.js +67 -67
  6. package/src/button/FullscreenButton.js +121 -121
  7. package/src/button/ZoomButtons.js +103 -103
  8. package/src/core/Dataset.js +154 -154
  9. package/src/core/Drawable.js +78 -78
  10. package/src/core/GeoCanvas.js +443 -443
  11. package/src/core/Layer.js +23 -23
  12. package/src/core/Legend.js +108 -108
  13. package/src/core/Map.js +568 -552
  14. package/src/core/MultiResolutionDataset.js +93 -93
  15. package/src/core/Style.js +98 -98
  16. package/src/core/Tooltip.js +182 -182
  17. package/src/dataset/COGeo.js +25 -25
  18. package/src/dataset/CSVGrid.js +112 -112
  19. package/src/dataset/GeoTIFF.js +122 -122
  20. package/src/dataset/JSGrid.js +55 -55
  21. package/src/dataset/TiledGrid.js +302 -302
  22. package/src/dataset/worker.js +18 -18
  23. package/src/index.js +79 -79
  24. package/src/layer/BackgroundLayer.js +173 -173
  25. package/src/layer/BackgroundLayerImage.js +81 -81
  26. package/src/layer/BackgroundLayerWMS.js +104 -104
  27. package/src/layer/GeoJSONLayer.js +276 -276
  28. package/src/layer/GridLayer.js +166 -166
  29. package/src/layer/LabelLayer.js +194 -194
  30. package/src/legend/ColorCategoryLegend.js +109 -109
  31. package/src/legend/ColorDiscreteLegend.js +100 -100
  32. package/src/legend/ColorLegend.js +115 -115
  33. package/src/legend/OrientationLegend.js +89 -89
  34. package/src/legend/SizeLegend.js +224 -224
  35. package/src/legend/TernaryLegend.js +302 -302
  36. package/src/style/CompositionStyle.js +291 -291
  37. package/src/style/DotDensityStyle.js +133 -133
  38. package/src/style/ImageStyle.js +100 -100
  39. package/src/style/Interpolator.js +258 -258
  40. package/src/style/IsoFenceStyle.js +217 -217
  41. package/src/style/JoyPlotStyle.js +180 -180
  42. package/src/style/LegoStyle.js +132 -132
  43. package/src/style/MosaicStyle.js +99 -99
  44. package/src/style/NinjaStarStyle.js +102 -102
  45. package/src/style/PillarStyle.js +207 -207
  46. package/src/style/SegmentStyle.js +105 -105
  47. package/src/style/ShadingRayStyle.js +280 -280
  48. package/src/style/ShadingStyle.js +72 -72
  49. package/src/style/ShapeColorSizeStyle.js +147 -147
  50. package/src/style/SideCategoryStyle.js +112 -112
  51. package/src/style/SideStyle.js +217 -217
  52. package/src/style/SideTanakaStyle.js +154 -154
  53. package/src/style/SquareColorCategoryWebGLStyle.js +307 -294
  54. package/src/style/SquareColorWebGLStyle.js +126 -126
  55. package/src/style/StrokeStyle.js +135 -135
  56. package/src/style/TextStyle.js +110 -110
  57. package/src/style/TimeSeriesStyle.js +222 -222
  58. package/src/utils/WebGLRectangleColoring.js +106 -106
  59. package/src/utils/WebGLSquareColoring.js +118 -118
  60. package/src/utils/WebGLSquareColoringAdvanced.js +227 -227
  61. package/src/utils/WebGLSquareColoringKS.js +153 -153
  62. package/src/utils/scale.js +255 -255
  63. package/src/utils/stretching.js +120 -120
  64. package/src/utils/ternary.js +208 -208
  65. package/src/utils/utils.js +125 -125
  66. package/src/utils/webGLUtils.js +73 -73
  67. package/src/utils/zoomUtils.js +142 -142
@@ -1,276 +1,276 @@
1
- //@ts-check
2
- 'use strict'
3
-
4
- import { Layer } from '../core/Layer.js'
5
- import { json } from 'd3-fetch'
6
-
7
- /**
8
- * @module layer
9
- * @author Joseph Davies, Julien Gaffuri
10
- */
11
- export class GeoJSONLayer extends Layer {
12
- /**
13
- * @param {object} opts
14
- */
15
- constructor(opts) {
16
- super(opts)
17
- opts = opts || {}
18
-
19
- /**
20
- * @private
21
- * @type {string} */
22
- this.url = opts.url
23
-
24
- /**
25
- * A preprocess to run on each feature after loading.
26
- * It can be used to apply some specific treatment before, format the label data, project coordinates, etc.
27
- * Return false if the label should not be kept.
28
- * @private
29
- * @type {function(object):boolean} */
30
- this.preprocess = opts.preprocess
31
-
32
- //for points
33
-
34
- /**
35
- * @private
36
- * @type {function(object,number):string} */
37
- this.shape = opts.shape || ((f, z) => 'circle')
38
- /**
39
- * In pixel
40
- * @private
41
- * @type {function(object,number):number} */
42
- this.size = opts.size || ((f, z) => 10)
43
-
44
- // for lines and polygon outlines
45
-
46
- /**
47
- * @private
48
- * @type {function(object,number):string} */
49
- this.strokeStyle = opts.strokeStyle || opts.color || ((f, z) => 'gray')
50
- /**
51
- * In pixel
52
- * @private
53
- * @type {function(object,number):number} */
54
- this.lineWidth = opts.lineWidth || opts.width || ((f, z) => 2)
55
- /**
56
- * @private
57
- * @type {function(object,number):Array.<number>|undefined} */
58
- this.lineDash = opts.lineDash || ((f, z) => undefined)
59
-
60
-
61
- // for polygon filling and point symbol filling
62
- /**
63
- * @private
64
- * @type {function(object,number):string} */
65
- this.fillStyle = opts.fillStyle || ((f, z) => 'black')
66
-
67
-
68
-
69
- /**
70
- * @private
71
- * @type {Array.<object> | undefined} */
72
- this.fs = undefined
73
-
74
- /**
75
- * @private
76
- * @type {string} */
77
- this.loadingStatus = 'notLoaded'
78
- }
79
-
80
- /**
81
- * Draw the layer.
82
- * @param {import("../core/GeoCanvas.js").GeoCanvas} geoCanvas The canvas where to draw the layer.
83
- * @returns {void}
84
- */
85
- draw(geoCanvas) {
86
- //load data, if not done yet.
87
- if (!this.fs) {
88
- this.load(geoCanvas.redraw)
89
- return
90
- }
91
-
92
- //
93
- const z = geoCanvas.view.z
94
- const ctx = geoCanvas.offscreenCtx
95
-
96
- // draw each feature
97
- for (const f of this.fs)
98
- this.drawGeometry(f, f.geometry, f.geometry.type, z, ctx)
99
-
100
- }
101
-
102
- /**
103
- * @private
104
- * Draw a geometry on the canvas, according to its type and the layer style.
105
- * @param {object} f The feature to draw
106
- * @param {object} geom The geometry of the feature to draw
107
- * @param {string} gt The geometry type (e.g. 'Point', 'LineString', etc.)
108
- * @param {number} z The current zoom level of the map
109
- * @param {CanvasRenderingContext2D} ctx The canvas context to draw on
110
- * @returns {void}
111
- */
112
- drawGeometry(f, geom, gt, z, ctx) {
113
- if (gt == 'Point' || gt == 'MultiPoint') {
114
-
115
- //get style parameters for the point feature
116
- const shape = this.shape(f, z)
117
- if (!shape || shape == 'none') return
118
- const size = this.size(f, z) * z
119
- if (!size) return
120
-
121
- const strokeStyle = this.strokeStyle(f, z)
122
- const fillStyle = this.fillStyle(f, z)
123
- const lineWidth = this.lineWidth(f, z) * z
124
-
125
- //set canvas drawing parameters
126
- ctx.save()
127
- if (strokeStyle) ctx.strokeStyle = strokeStyle
128
- if (fillStyle) ctx.fillStyle = fillStyle
129
- if (lineWidth) ctx.lineWidth = lineWidth
130
-
131
- let cs = geom.coordinates
132
- if (gt == 'Point') cs = [cs]
133
-
134
- if (shape == 'circle') {
135
- //draw circle - fill and stroke
136
- for (const c of cs) {
137
- ctx.beginPath()
138
- ctx.arc(c[0], c[1], size / 2, 0, 2 * Math.PI, false)
139
- if (fillStyle) ctx.fill()
140
- if (strokeStyle && lineWidth) ctx.stroke()
141
- }
142
- } else if (shape == 'square') {
143
- //draw square - fill and stroke
144
- for (const c of cs) {
145
- ctx.beginPath()
146
- ctx.rect(c[0] - size / 2, c[1] - size / 2, size, size)
147
- if (fillStyle) ctx.fill()
148
- if (strokeStyle && lineWidth) ctx.stroke()
149
- }
150
- } else {
151
- console.error('Unexpected shape for point GeoJSON: ' + shape)
152
- }
153
- ctx.restore()
154
-
155
- } else if (gt == 'LineString' || gt == 'MultiLineString') {
156
-
157
- const col = this.strokeStyle(f, z)
158
- if (!col || col === 'none') return
159
-
160
- const wP = this.lineWidth(f, z)
161
- if (!wP || wP < 0) return
162
-
163
- ctx.save()
164
- ctx.strokeStyle = col
165
- ctx.lineWidth = wP * z
166
- ctx.setLineDash(this.lineDash(f, z) || [])
167
-
168
- //
169
- const css = gt === 'LineString' ? [geom.coordinates] : geom.coordinates
170
-
171
- for (const cs of css) {
172
- if (cs.length < 2) continue
173
- ctx.beginPath()
174
- ctx.moveTo(cs[0][0], cs[0][1])
175
- for (let i = 1; i < cs.length; i++) ctx.lineTo(cs[i][0], cs[i][1])
176
- ctx.stroke()
177
- }
178
-
179
- ctx.restore()
180
-
181
- } else if (gt == 'Polygon' || gt == 'MultiPolygon') {
182
- ctx.save()
183
-
184
- // A Polygon is [ outerRing, ...holes ]. A MultiPolygon is [ [ outerRing, ...holes ], ... ]
185
- const polygons = gt === 'Polygon' ? [geom.coordinates] : geom.coordinates
186
-
187
- ctx.beginPath()
188
-
189
- for (const rings of polygons) {
190
- for (const cs of rings) {
191
- if (cs.length < 2) continue
192
- ctx.moveTo(cs[0][0], cs[0][1])
193
- for (let i = 1; i < cs.length; i++) ctx.lineTo(cs[i][0], cs[i][1])
194
- ctx.closePath()
195
- }
196
- }
197
-
198
- // Fill
199
- const fillStyle = this.fillStyle(f, z)
200
- if (fillStyle && fillStyle !== 'none') {
201
- ctx.fillStyle = fillStyle
202
- ctx.fill('evenodd') // even-odd punches holes correctly regardless of ring winding order
203
- }
204
-
205
- // Stroke (optional, only if style provides a width)
206
- const wP = this.lineWidth(f, z)
207
- if (wP && wP > 0) {
208
- const strokeStyle = this.strokeStyle?.(f, z) ?? fillStyle
209
- if (strokeStyle && strokeStyle !== 'none') {
210
- ctx.strokeStyle = strokeStyle
211
- ctx.lineWidth = wP * z
212
- ctx.setLineDash(this.lineDash?.(f, z) || [])
213
- ctx.stroke()
214
- }
215
- }
216
- ctx.restore()
217
-
218
- } else if (gt == 'GeometryCollection') {
219
- //recursive call for each geometry in the collection
220
- for (const g of geom.geometries)
221
- this.drawGeometry(f, g, g.type, z, ctx)
222
-
223
- } else {
224
- console.log('Unexpected geometry type in GeoJSONLayer: ' + gt)
225
- }
226
- }
227
-
228
- /**
229
- * Load data for labels, from URL this.url
230
- * @param {function():void} callback
231
- * @private
232
- */
233
- async load(callback) {
234
- if (!this.url) {
235
- console.log('Failed loading GeoJSON data: No URL specified. ' + this.url)
236
- this.loadingStatus = 'failed'
237
- this.labels = []
238
- return
239
- }
240
-
241
- //check if data already loaded
242
- if (this.loadingStatus != 'notLoaded') return
243
-
244
- //load data
245
- this.loadingStatus = 'loading'
246
-
247
- try {
248
- const data_ = await json(this.url)
249
-
250
- /** @type { Array.<object> } */
251
- const data = data_.features
252
-
253
- //preprocess/filter
254
- if (this.preprocess) {
255
- this.fs = []
256
- for (const c of data) {
257
- const b = this.preprocess(c)
258
- if (b == false) continue
259
- this.fs.push(c)
260
- }
261
- } else {
262
- //store labels
263
- this.fs = data
264
- }
265
-
266
- this.loadingStatus = 'loaded'
267
-
268
- //redraw
269
- if (callback) callback()
270
- } catch (error) {
271
- console.log('Failed loading GeoJSON from ' + this.url)
272
- this.fs = []
273
- this.loadingStatus = 'failed'
274
- }
275
- }
276
- }
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ import { Layer } from '../core/Layer.js'
5
+ import { json } from 'd3-fetch'
6
+
7
+ /**
8
+ * @module layer
9
+ * @author Joseph Davies, Julien Gaffuri
10
+ */
11
+ export class GeoJSONLayer extends Layer {
12
+ /**
13
+ * @param {object} opts
14
+ */
15
+ constructor(opts) {
16
+ super(opts)
17
+ opts = opts || {}
18
+
19
+ /**
20
+ * @private
21
+ * @type {string} */
22
+ this.url = opts.url
23
+
24
+ /**
25
+ * A preprocess to run on each feature after loading.
26
+ * It can be used to apply some specific treatment before, format the label data, project coordinates, etc.
27
+ * Return false if the label should not be kept.
28
+ * @private
29
+ * @type {function(object):boolean} */
30
+ this.preprocess = opts.preprocess
31
+
32
+ //for points
33
+
34
+ /**
35
+ * @private
36
+ * @type {function(object,number):string} */
37
+ this.shape = opts.shape || ((f, z) => 'circle')
38
+ /**
39
+ * In pixel
40
+ * @private
41
+ * @type {function(object,number):number} */
42
+ this.size = opts.size || ((f, z) => 10)
43
+
44
+ // for lines and polygon outlines
45
+
46
+ /**
47
+ * @private
48
+ * @type {function(object,number):string} */
49
+ this.strokeStyle = opts.strokeStyle || opts.color || ((f, z) => 'gray')
50
+ /**
51
+ * In pixel
52
+ * @private
53
+ * @type {function(object,number):number} */
54
+ this.lineWidth = opts.lineWidth || opts.width || ((f, z) => 2)
55
+ /**
56
+ * @private
57
+ * @type {function(object,number):Array.<number>|undefined} */
58
+ this.lineDash = opts.lineDash || ((f, z) => undefined)
59
+
60
+
61
+ // for polygon filling and point symbol filling
62
+ /**
63
+ * @private
64
+ * @type {function(object,number):string} */
65
+ this.fillStyle = opts.fillStyle || ((f, z) => 'black')
66
+
67
+
68
+
69
+ /**
70
+ * @private
71
+ * @type {Array.<object> | undefined} */
72
+ this.fs = undefined
73
+
74
+ /**
75
+ * @private
76
+ * @type {string} */
77
+ this.loadingStatus = 'notLoaded'
78
+ }
79
+
80
+ /**
81
+ * Draw the layer.
82
+ * @param {import("../core/GeoCanvas.js").GeoCanvas} geoCanvas The canvas where to draw the layer.
83
+ * @returns {void}
84
+ */
85
+ draw(geoCanvas) {
86
+ //load data, if not done yet.
87
+ if (!this.fs) {
88
+ this.load(geoCanvas.redraw)
89
+ return
90
+ }
91
+
92
+ //
93
+ const z = geoCanvas.view.z
94
+ const ctx = geoCanvas.offscreenCtx
95
+
96
+ // draw each feature
97
+ for (const f of this.fs)
98
+ this.drawGeometry(f, f.geometry, f.geometry.type, z, ctx)
99
+
100
+ }
101
+
102
+ /**
103
+ * @private
104
+ * Draw a geometry on the canvas, according to its type and the layer style.
105
+ * @param {object} f The feature to draw
106
+ * @param {object} geom The geometry of the feature to draw
107
+ * @param {string} gt The geometry type (e.g. 'Point', 'LineString', etc.)
108
+ * @param {number} z The current zoom level of the map
109
+ * @param {CanvasRenderingContext2D} ctx The canvas context to draw on
110
+ * @returns {void}
111
+ */
112
+ drawGeometry(f, geom, gt, z, ctx) {
113
+ if (gt == 'Point' || gt == 'MultiPoint') {
114
+
115
+ //get style parameters for the point feature
116
+ const shape = this.shape(f, z)
117
+ if (!shape || shape == 'none') return
118
+ const size = this.size(f, z) * z
119
+ if (!size) return
120
+
121
+ const strokeStyle = this.strokeStyle(f, z)
122
+ const fillStyle = this.fillStyle(f, z)
123
+ const lineWidth = this.lineWidth(f, z) * z
124
+
125
+ //set canvas drawing parameters
126
+ ctx.save()
127
+ if (strokeStyle) ctx.strokeStyle = strokeStyle
128
+ if (fillStyle) ctx.fillStyle = fillStyle
129
+ if (lineWidth) ctx.lineWidth = lineWidth
130
+
131
+ let cs = geom.coordinates
132
+ if (gt == 'Point') cs = [cs]
133
+
134
+ if (shape == 'circle') {
135
+ //draw circle - fill and stroke
136
+ for (const c of cs) {
137
+ ctx.beginPath()
138
+ ctx.arc(c[0], c[1], size / 2, 0, 2 * Math.PI, false)
139
+ if (fillStyle) ctx.fill()
140
+ if (strokeStyle && lineWidth) ctx.stroke()
141
+ }
142
+ } else if (shape == 'square') {
143
+ //draw square - fill and stroke
144
+ for (const c of cs) {
145
+ ctx.beginPath()
146
+ ctx.rect(c[0] - size / 2, c[1] - size / 2, size, size)
147
+ if (fillStyle) ctx.fill()
148
+ if (strokeStyle && lineWidth) ctx.stroke()
149
+ }
150
+ } else {
151
+ console.error('Unexpected shape for point GeoJSON: ' + shape)
152
+ }
153
+ ctx.restore()
154
+
155
+ } else if (gt == 'LineString' || gt == 'MultiLineString') {
156
+
157
+ const col = this.strokeStyle(f, z)
158
+ if (!col || col === 'none') return
159
+
160
+ const wP = this.lineWidth(f, z)
161
+ if (!wP || wP < 0) return
162
+
163
+ ctx.save()
164
+ ctx.strokeStyle = col
165
+ ctx.lineWidth = wP * z
166
+ ctx.setLineDash(this.lineDash(f, z) || [])
167
+
168
+ //
169
+ const css = gt === 'LineString' ? [geom.coordinates] : geom.coordinates
170
+
171
+ for (const cs of css) {
172
+ if (cs.length < 2) continue
173
+ ctx.beginPath()
174
+ ctx.moveTo(cs[0][0], cs[0][1])
175
+ for (let i = 1; i < cs.length; i++) ctx.lineTo(cs[i][0], cs[i][1])
176
+ ctx.stroke()
177
+ }
178
+
179
+ ctx.restore()
180
+
181
+ } else if (gt == 'Polygon' || gt == 'MultiPolygon') {
182
+ ctx.save()
183
+
184
+ // A Polygon is [ outerRing, ...holes ]. A MultiPolygon is [ [ outerRing, ...holes ], ... ]
185
+ const polygons = gt === 'Polygon' ? [geom.coordinates] : geom.coordinates
186
+
187
+ ctx.beginPath()
188
+
189
+ for (const rings of polygons) {
190
+ for (const cs of rings) {
191
+ if (cs.length < 2) continue
192
+ ctx.moveTo(cs[0][0], cs[0][1])
193
+ for (let i = 1; i < cs.length; i++) ctx.lineTo(cs[i][0], cs[i][1])
194
+ ctx.closePath()
195
+ }
196
+ }
197
+
198
+ // Fill
199
+ const fillStyle = this.fillStyle(f, z)
200
+ if (fillStyle && fillStyle !== 'none') {
201
+ ctx.fillStyle = fillStyle
202
+ ctx.fill('evenodd') // even-odd punches holes correctly regardless of ring winding order
203
+ }
204
+
205
+ // Stroke (optional, only if style provides a width)
206
+ const wP = this.lineWidth(f, z)
207
+ if (wP && wP > 0) {
208
+ const strokeStyle = this.strokeStyle?.(f, z) ?? fillStyle
209
+ if (strokeStyle && strokeStyle !== 'none') {
210
+ ctx.strokeStyle = strokeStyle
211
+ ctx.lineWidth = wP * z
212
+ ctx.setLineDash(this.lineDash?.(f, z) || [])
213
+ ctx.stroke()
214
+ }
215
+ }
216
+ ctx.restore()
217
+
218
+ } else if (gt == 'GeometryCollection') {
219
+ //recursive call for each geometry in the collection
220
+ for (const g of geom.geometries)
221
+ this.drawGeometry(f, g, g.type, z, ctx)
222
+
223
+ } else {
224
+ console.log('Unexpected geometry type in GeoJSONLayer: ' + gt)
225
+ }
226
+ }
227
+
228
+ /**
229
+ * Load data for labels, from URL this.url
230
+ * @param {function():void} callback
231
+ * @private
232
+ */
233
+ async load(callback) {
234
+ if (!this.url) {
235
+ console.log('Failed loading GeoJSON data: No URL specified. ' + this.url)
236
+ this.loadingStatus = 'failed'
237
+ this.labels = []
238
+ return
239
+ }
240
+
241
+ //check if data already loaded
242
+ if (this.loadingStatus != 'notLoaded') return
243
+
244
+ //load data
245
+ this.loadingStatus = 'loading'
246
+
247
+ try {
248
+ const data_ = await json(this.url)
249
+
250
+ /** @type { Array.<object> } */
251
+ const data = data_.features
252
+
253
+ //preprocess/filter
254
+ if (this.preprocess) {
255
+ this.fs = []
256
+ for (const c of data) {
257
+ const b = this.preprocess(c)
258
+ if (b == false) continue
259
+ this.fs.push(c)
260
+ }
261
+ } else {
262
+ //store labels
263
+ this.fs = data
264
+ }
265
+
266
+ this.loadingStatus = 'loaded'
267
+
268
+ //redraw
269
+ if (callback) callback()
270
+ } catch (error) {
271
+ console.log('Failed loading GeoJSON from ' + this.url)
272
+ this.fs = []
273
+ this.loadingStatus = 'failed'
274
+ }
275
+ }
276
+ }