gridviz 2.1.17 → 3.0.0

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 +2 -3
  2. package/dist/gridviz.js +4971 -5654
  3. package/dist/gridviz.min.js +1 -1
  4. package/package.json +3 -2
  5. package/src/button/Button.js +14 -15
  6. package/src/button/FullscreenButton.js +14 -14
  7. package/src/button/ZoomButtons.js +2 -2
  8. package/src/{DatasetComponent.js → core/Dataset.js} +33 -12
  9. package/src/core/Drawable.js +60 -0
  10. package/src/{GeoCanvas.js → core/GeoCanvas.js} +65 -155
  11. package/src/core/Layer.js +24 -0
  12. package/src/{Legend.js → core/Legend.js} +24 -1
  13. package/src/core/Map.js +460 -0
  14. package/src/core/MultiResolutionDataset.js +96 -0
  15. package/src/core/Style.js +84 -0
  16. package/src/dataset/COGeo.js +5 -5
  17. package/src/dataset/CSVGrid.js +43 -41
  18. package/src/dataset/GeoTIFF.js +9 -14
  19. package/src/dataset/{LGrid.js → JSGrid.js} +9 -10
  20. package/src/dataset/TiledGrid.js +68 -45
  21. package/src/index.js +22 -29
  22. package/src/{BackgroundLayer.js → layer/BackgroundLayer.js} +27 -52
  23. package/src/{BackgroundLayerWMS.js → layer/BackgroundLayerWMS.js} +21 -45
  24. package/src/{LineLayer.js → layer/GeoJSONLayer.js} +22 -23
  25. package/src/layer/GridLayer.js +140 -0
  26. package/src/{LabelLayer.js → layer/LabelLayer.js} +25 -23
  27. package/src/legend/ColorCategoryLegend.js +9 -24
  28. package/src/legend/ColorDiscreteLegend.js +20 -24
  29. package/src/legend/ColorLegend.js +21 -33
  30. package/src/legend/OrientationLegend.js +90 -0
  31. package/src/legend/SizeLegend.js +153 -72
  32. package/src/style/CompositionStyle.js +71 -84
  33. package/src/style/ContourStyle.js +2 -36
  34. package/src/style/DotDensityStyle.js +50 -73
  35. package/src/style/IsoFenceStyle.js +59 -70
  36. package/src/style/JoyPlotStyle.js +41 -48
  37. package/src/style/LegoStyle.js +4 -4
  38. package/src/style/MosaicStyle.js +30 -39
  39. package/src/style/NinjaStarStyle.js +45 -68
  40. package/src/style/PillarStyle.js +70 -93
  41. package/src/style/SegmentStyle.js +37 -75
  42. package/src/style/ShapeColorSizeStyle.js +49 -98
  43. package/src/style/SideCategoryStyle.js +112 -0
  44. package/src/style/SideStyle.js +99 -133
  45. package/src/style/{SquareColorCatWGLStyle.js → SquareColorCategoryWebGLStyle.js} +28 -41
  46. package/src/style/{SquareColorWGLStyle.js → SquareColorWebGLStyle.js} +28 -49
  47. package/src/style/StrokeStyle.js +43 -70
  48. package/src/style/TanakaStyle.js +34 -132
  49. package/src/style/TextStyle.js +43 -64
  50. package/src/style/TimeSeriesStyle.js +44 -75
  51. package/src/utils/WebGLSquareColoringAdvanced.js +4 -4
  52. package/src/utils/scale.js +202 -0
  53. package/src/utils/stretching.js +86 -129
  54. package/src/utils/{Utils.js → utils.js} +15 -0
  55. package/src/utils/webGLUtils.js +4 -5
  56. package/src/utils/zoomUtils.js +30 -30
  57. package/src/App.js +0 -760
  58. package/src/Dataset.js +0 -76
  59. package/src/Layer.js +0 -103
  60. package/src/Style.js +0 -131
  61. package/src/dataset/GridTile.js +0 -41
  62. package/src/legend/SegmentOrientationLegend.js +0 -87
  63. package/src/legend/SegmentWidthLegend.js +0 -101
  64. package/src/style/CompositionStyle_.js +0 -293
  65. package/src/style/ShapeColorSizeStyle_.js +0 -108
  66. package/src/style/SideCatStyle.js +0 -172
  67. /package/src/{Tooltip.js → core/Tooltip.js} +0 -0
package/src/index.js CHANGED
@@ -2,65 +2,58 @@
2
2
  'use strict'
3
3
 
4
4
  // the application
5
- export { App } from './App.js'
6
- export { GeoCanvas } from './GeoCanvas.js'
7
- export { Style } from './Style.js'
8
- export { Layer } from './Layer.js'
9
- export { Dataset } from './Dataset.js'
10
- export { DatasetComponent } from './DatasetComponent.js'
5
+ export { Map } from './core/Map.js'
6
+ //export { GeoCanvas } from './GeoCanvas.js'
7
+ export { Style } from './core/Style.js'
8
+ export { Layer } from './core/Layer.js'
9
+ export { MultiResolutionDataset } from './core/MultiResolutionDataset.js'
11
10
 
12
11
  // export dataset types
13
12
  export { TiledGrid } from './dataset/TiledGrid.js'
14
- export { GridTile } from './dataset/GridTile.js'
15
13
  export { CSVGrid } from './dataset/CSVGrid.js'
16
- export { LGrid } from './dataset/LGrid.js'
17
- //export { GeoTIFF } from "./dataset/GeoTIFF"
14
+ export { JSGrid } from './dataset/JSGrid.js'
18
15
 
19
16
  // export styles
20
17
  export { ShapeColorSizeStyle } from './style/ShapeColorSizeStyle.js'
21
- export { ShapeColorSizeStyle_ } from './style/ShapeColorSizeStyle_.js'
22
18
  export { StrokeStyle } from './style/StrokeStyle.js'
23
19
  export { JoyPlotStyle } from './style/JoyPlotStyle.js'
24
20
  export { CompositionStyle } from './style/CompositionStyle.js'
25
- export { CompositionStyle_ } from './style/CompositionStyle_.js'
26
21
  export { SegmentStyle } from './style/SegmentStyle.js'
27
22
  export { TextStyle } from './style/TextStyle.js'
28
23
  export { PillarStyle } from './style/PillarStyle.js'
29
24
  export { SideStyle } from './style/SideStyle.js'
30
- export { ContourStyle } from './style/ContourStyle.js'
31
- export { SideCatStyle } from './style/SideCatStyle.js'
25
+ //export { ContourStyle } from './style/ContourStyle.js'
26
+ export { SideCategoryStyle } from './style/SideCategoryStyle.js'
32
27
  export { DotDensityStyle } from './style/DotDensityStyle.js'
33
- export { TanakaStyle } from './style/TanakaStyle.js'
34
- export { LegoStyle } from './style/LegoStyle.js'
35
- export { SquareColorWGLStyle } from './style/SquareColorWGLStyle.js'
36
- export { SquareColorCatWGLStyle } from './style/SquareColorCatWGLStyle.js'
28
+ //export { TanakaStyle } from './style/TanakaStyle.js'
29
+ //export { LegoStyle } from './style/LegoStyle.js'
30
+ export { SquareColorWebGLStyle } from './style/SquareColorWebGLStyle.js'
31
+ export { SquareColorCategoryWebGLStyle } from './style/SquareColorCategoryWebGLStyle.js'
37
32
  export { MosaicStyle } from './style/MosaicStyle.js'
38
33
  export { NinjaStarStyle } from './style/NinjaStarStyle.js'
39
34
  export { TimeSeriesStyle } from './style/TimeSeriesStyle.js'
40
35
  export { IsoFenceStyle } from './style/IsoFenceStyle.js'
41
36
 
42
37
  // export additional layers
43
- export { BackgroundLayer } from './BackgroundLayer.js'
44
- export { BackgroundLayerWMS } from './BackgroundLayerWMS.js'
45
- export { LabelLayer } from './LabelLayer.js'
46
- export { LineLayer as BoundaryLayer } from './LineLayer.js'
38
+ export { GridLayer } from './layer/GridLayer.js'
39
+ export { BackgroundLayer } from './layer/BackgroundLayer.js'
40
+ export { BackgroundLayerWMS } from './layer/BackgroundLayerWMS.js'
41
+ export { LabelLayer } from './layer/LabelLayer.js'
42
+ export { GeoJSONLayer } from './layer/GeoJSONLayer.js'
47
43
 
48
44
  // export legends
49
45
  export { ColorLegend } from './legend/ColorLegend.js'
50
46
  export { ColorDiscreteLegend } from './legend/ColorDiscreteLegend.js'
51
47
  export { ColorCategoryLegend } from './legend/ColorCategoryLegend.js'
52
- export { SizeLegend } from './legend/SizeLegend.js'
53
- export { SegmentWidthLegend } from './legend/SegmentWidthLegend.js'
54
- export { SegmentOrientationLegend } from './legend/SegmentOrientationLegend.js'
48
+ export { SizeLegend, sizeLegend, sizeLegendViewScale, sizeDiscreteLegend, sizeDiscreteViewScaleLegend } from './legend/SizeLegend.js'
49
+ export { OrientationLegend, orientationLegend } from './legend/OrientationLegend.js'
55
50
 
56
51
  // export { goToStraight, zoomTo } from "./utils/zoomUtils"
57
52
  export * from './utils/stretching.js'
53
+ export * from './utils/scale.js'
54
+ export { nice } from './utils/utils.js'
58
55
 
59
- export { getClass } from './utils/Utils.js'
60
-
61
-
62
-
63
- import { GeoCanvas } from './GeoCanvas.js'
56
+ import { GeoCanvas } from './core/GeoCanvas.js'
64
57
  export const getParameterByName = GeoCanvas.getParameterByName
65
58
 
66
59
  // set default d3 locale
@@ -1,6 +1,8 @@
1
1
  //@ts-check
2
2
  'use strict'
3
3
 
4
+ import { Layer } from '../core/Layer.js'
5
+
4
6
  /**
5
7
  *
6
8
  * A map background layer in "Slippy map" XYZ standard.
@@ -9,29 +11,14 @@
9
11
  *
10
12
  * @author Julien Gaffuri
11
13
  */
12
- export class BackgroundLayer {
14
+ export class BackgroundLayer extends Layer {
13
15
  /**
14
16
  * @param {object} opts
15
17
  */
16
18
  constructor(opts) {
19
+ super(opts)
17
20
  opts = opts || {}
18
21
 
19
- /** An attribute to specify if a layer should be drawn or not
20
- * @type {boolean} */
21
- this.visible = opts.visible == false ? false : true
22
-
23
- /** The minimum zoom factor: Below this level, the layer is not shown.
24
- * @type {number} */
25
- this.minZoom = opts.minZoom || 0
26
-
27
- /** The maximum zoom factor: Above this level, the layer is not shown.
28
- * @type {number} */
29
- this.maxZoom = opts.maxZoom || Infinity
30
-
31
- //ensure acceptable values for the zoom limits.
32
- if (this.minZoom >= this.maxZoom)
33
- throw new Error('Unexpected zoom limits for layer. Zoom min should be smaller than zoom max.')
34
-
35
22
  /** The image cache, indexed by z/y/x */
36
23
  this.cache = {}
37
24
 
@@ -53,9 +40,6 @@ export class BackgroundLayer {
53
40
  this.origin = opts.origin || [0, 0]
54
41
  /** @type {number} */
55
42
  this.z0 = opts.z0 || 0
56
-
57
- /** @type {function(number):string} */
58
- this.filterColor = opts.filterColor // (zf) => "#eee7"
59
43
  }
60
44
 
61
45
  /**
@@ -90,63 +74,61 @@ export class BackgroundLayer {
90
74
  }
91
75
 
92
76
  /**
93
- * @param {import("./GeoCanvas").GeoCanvas} cg The canvas where to draw the layer.
77
+ * @param {import("../core/GeoCanvas").GeoCanvas} geoCanvas The canvas where to draw the layer.
94
78
  * @returns {void}
95
79
  */
96
- draw(cg) {
80
+ draw(geoCanvas) {
81
+
97
82
  if (!this.resolutions || this.resolutions.length == 0) {
98
83
  console.error('No resolutions provided for background layer')
99
84
  return
100
85
  }
101
86
 
102
87
  //
103
- const zf = cg.getZf()
88
+ const z = geoCanvas.view.z
104
89
  const x0 = this.origin[0],
105
90
  y0 = this.origin[1]
106
91
 
107
92
  //get zoom level and resolution
108
- let z = 0
109
- for (z = 0; z < this.resolutions.length; z++) if (this.resolutions[z] < zf) break
110
- z -= 1
111
- z = Math.max(0, z)
112
- z = Math.min(z, this.resolutions.length - 1)
93
+ let z_ = 0
94
+ for (z_ = 0; z_ < this.resolutions.length; z_++) if (this.resolutions[z_] < z) break
95
+ z_ -= 1
96
+ z_ = Math.max(0, z_)
97
+ z_ = Math.min(z_, this.resolutions.length - 1)
113
98
  //console.log(this.resolutions.length, z)
114
- const res = this.resolutions[z]
99
+ const res = this.resolutions[z_]
115
100
 
116
- z += this.z0
101
+ z_ += this.z0
117
102
 
118
103
  const sizeG = this.nbPix * res
119
- const size = sizeG / zf
104
+ const size = sizeG / z
120
105
 
121
106
  //get tile numbers
122
107
  const xGeoToTMS = (x) => Math.ceil((x - x0) / sizeG)
123
108
  const yGeoToTMS = (y) => Math.ceil(-(y - y0) / sizeG)
124
- const xMin = xGeoToTMS(cg.extGeo.xMin) - 1
125
- const xMax = xGeoToTMS(cg.extGeo.xMax)
126
- const yMax = yGeoToTMS(cg.extGeo.yMin)
127
- const yMin = yGeoToTMS(cg.extGeo.yMax) - 1
128
-
129
- //TODO ?
130
- //cg.setCanvasTransform()
109
+ const xMin = xGeoToTMS(geoCanvas.extGeo.xMin) - 1
110
+ const xMax = xGeoToTMS(geoCanvas.extGeo.xMax)
111
+ const yMax = yGeoToTMS(geoCanvas.extGeo.yMin)
112
+ const yMin = yGeoToTMS(geoCanvas.extGeo.yMax) - 1
131
113
 
132
114
  //handle images
133
115
  for (let x = xMin; x < xMax; x++) {
134
116
  for (let y = yMin; y < yMax; y++) {
135
117
  //get image
136
- let img = this.get(z, x, y)
118
+ let img = this.get(z_, x, y)
137
119
 
138
120
  //load image
139
121
  if (!img) {
140
122
  const img = new Image()
141
- this.put(img, z, x, y)
123
+ this.put(img, z_, x, y)
142
124
  img.onload = () => {
143
- cg.redraw()
125
+ geoCanvas.redraw()
144
126
  }
145
127
  img.onerror = () => {
146
128
  //case when no image
147
- this.put('failed', z, x, y)
129
+ this.put('failed', z_, x, y)
148
130
  }
149
- img.src = this.urlFun(x, y, z)
131
+ img.src = this.urlFun(x, y, z_)
150
132
  continue
151
133
  }
152
134
 
@@ -162,7 +144,8 @@ export class BackgroundLayer {
162
144
  const xGeo = x0 + x * sizeG
163
145
  const yGeo = y0 - y * sizeG
164
146
  try {
165
- cg.ctx.drawImage(img, cg.geoToPixX(xGeo), cg.geoToPixY(yGeo), size, size)
147
+ geoCanvas.initCanvasTransform()
148
+ geoCanvas.ctx.drawImage(img, geoCanvas.geoToPixX(xGeo), geoCanvas.geoToPixY(yGeo), size, size)
166
149
  //cg.ctx.drawImage(img, xGeo, yGeo, sizeG, -sizeG)
167
150
  } catch (error) {
168
151
  console.error(error)
@@ -170,13 +153,5 @@ export class BackgroundLayer {
170
153
  }
171
154
  }
172
155
 
173
- //apply filter
174
- if (this.filterColor) {
175
- const fc = this.filterColor(zf)
176
- if (fc && fc != 'none') {
177
- cg.ctx.fillStyle = fc
178
- cg.ctx.fillRect(0, 0, cg.w, cg.h)
179
- }
180
- }
181
156
  }
182
157
  }
@@ -1,42 +1,26 @@
1
1
  //@ts-check
2
2
  'use strict'
3
3
 
4
+ import { Layer } from '../core/Layer.js'
5
+
4
6
  /**
5
7
  *
6
8
  * A map WMS background layer.
7
9
  *
8
10
  * @author Julien Gaffuri
9
11
  */
10
- export class BackgroundLayerWMS {
12
+ export class BackgroundLayerWMS extends Layer {
11
13
  /**
12
14
  * @param {object} opts
13
15
  */
14
16
  constructor(opts) {
17
+ super(opts)
15
18
  opts = opts || {}
16
19
 
17
- /** An attribute to specify if a layer should be drawn or not
18
- * @type {boolean} */
19
- this.visible = opts.visible == false ? false : true
20
-
21
- /** The minimum zoom factor: Below this level, the layer is not shown.
22
- * @type {number} */
23
- this.minZoom = opts.minZoom || 0
24
-
25
- /** The maximum zoom factor: Above this level, the layer is not shown.
26
- * @type {number} */
27
- this.maxZoom = opts.maxZoom || Infinity
28
-
29
- //ensure acceptable values for the zoom limits.
30
- if (this.minZoom >= this.maxZoom)
31
- throw new Error('Unexpected zoom limits for layer. Zoom min should be smaller than zoom max.')
32
-
33
20
  /**
34
21
  * @type {string} */
35
22
  this.url = opts.url
36
23
 
37
- /** @type {function(number):string} */
38
- this.filterColor = opts.filterColor // (zf) => "#eee7"
39
-
40
24
  /** @type {HTMLImageElement|undefined} */
41
25
  this.img = undefined;
42
26
 
@@ -62,43 +46,44 @@ export class BackgroundLayerWMS {
62
46
 
63
47
 
64
48
  /**
65
- * @param {import("./GeoCanvas").GeoCanvas} cg The canvas where to draw the layer.
49
+ * @param {import("../core/GeoCanvas").GeoCanvas} geoCanvas The canvas where to draw the layer.
66
50
  * @returns {void}
67
51
  */
68
- draw(cg) {
52
+ draw(geoCanvas) {
69
53
 
70
54
  //update map extent
71
- cg.updateExtentGeo(0)
55
+ geoCanvas.updateExtentGeo(0)
72
56
 
73
- if (!this.hasMoved(cg.extGeo) && this.img) {
57
+ if (!this.hasMoved(geoCanvas.extGeo) && this.img) {
74
58
  //the map did not move and the image was already downloaded: draw the image
75
- cg.ctx.drawImage(this.img, 0, 0, cg.w, cg.h)
59
+ geoCanvas.initCanvasTransform()
60
+ geoCanvas.ctx.drawImage(this.img, 0, 0, geoCanvas.w, geoCanvas.h)
76
61
 
77
62
  } else {
78
63
  //the map moved: retrieve new image
79
64
 
80
65
  //
81
- this.xMin = cg.extGeo.xMin
82
- this.xMax = cg.extGeo.xMax
83
- this.yMin = cg.extGeo.yMin
84
- this.yMax = cg.extGeo.yMax
66
+ this.xMin = geoCanvas.extGeo.xMin
67
+ this.xMax = geoCanvas.extGeo.xMax
68
+ this.yMin = geoCanvas.extGeo.yMin
69
+ this.yMax = geoCanvas.extGeo.yMax
85
70
 
86
71
  //build WMS URL
87
72
  const url = []
88
73
  url.push(this.url)
89
74
  url.push("&width=")
90
- url.push(cg.w)
75
+ url.push(geoCanvas.w)
91
76
  url.push("&height=")
92
- url.push(cg.h)
77
+ url.push(geoCanvas.h)
93
78
  //bbox: xmin ymin xmax ymax
94
79
  url.push("&bbox=")
95
- url.push(cg.extGeo.xMin)
80
+ url.push(geoCanvas.extGeo.xMin)
96
81
  url.push(",")
97
- url.push(cg.extGeo.yMin)
82
+ url.push(geoCanvas.extGeo.yMin)
98
83
  url.push(",")
99
- url.push(cg.extGeo.xMax)
84
+ url.push(geoCanvas.extGeo.xMax)
100
85
  url.push(",")
101
- url.push(cg.extGeo.yMax)
86
+ url.push(geoCanvas.extGeo.yMax)
102
87
 
103
88
  const urlS = url.join("")
104
89
  //console.log(urlS)
@@ -106,7 +91,7 @@ export class BackgroundLayerWMS {
106
91
  if (!this.img) {
107
92
  this.img = new Image()
108
93
  this.img.onload = () => {
109
- cg.redraw()
94
+ geoCanvas.redraw()
110
95
  }
111
96
  this.img.onerror = () => {
112
97
  //case when no image
@@ -118,14 +103,5 @@ export class BackgroundLayerWMS {
118
103
  this.img.src = urlS
119
104
  }
120
105
 
121
- //apply filter
122
- const zf = cg.getZf()
123
- if (this.filterColor) {
124
- const fc = this.filterColor(zf)
125
- if (fc && fc != 'none') {
126
- cg.ctx.fillStyle = fc
127
- cg.ctx.fillRect(0, 0, cg.w, cg.h)
128
- }
129
- }
130
106
  }
131
107
  }
@@ -1,16 +1,18 @@
1
1
  //@ts-check
2
2
  'use strict'
3
3
 
4
+ import { Layer } from '../core/Layer.js'
4
5
  import { json } from 'd3-fetch'
5
6
 
6
7
  /**
7
8
  * @author Joseph Davies, Julien Gaffuri
8
9
  */
9
- export class LineLayer {
10
+ export class GeoJSONLayer extends Layer {
10
11
  /**
11
12
  * @param {object} opts
12
13
  */
13
14
  constructor(opts) {
15
+ super(opts)
14
16
  opts = opts || {}
15
17
 
16
18
  /**
@@ -29,15 +31,15 @@ export class LineLayer {
29
31
  /**
30
32
  * @private
31
33
  * @type {function(object,number):string} */
32
- this.color = opts.color || ((f, zf) => 'gray')
34
+ this.color = opts.color || ((f, z) => 'gray')
33
35
  /**
34
36
  * @private
35
37
  * @type {function(object,number):number} */
36
- this.width = opts.width || ((f, zf) => 2)
38
+ this.width = opts.width || ((f, z) => 2)
37
39
  /**
38
40
  * @private
39
41
  * @type {function(object,number):Array.<number>|undefined} */
40
- this.lineDash = opts.lineDash || ((f, zf) => undefined)
42
+ this.lineDash = opts.lineDash || ((f, z) => undefined)
41
43
 
42
44
  /**
43
45
  * @private
@@ -52,51 +54,48 @@ export class LineLayer {
52
54
 
53
55
  /**
54
56
  * Draw the layer.
55
- * @param {import("./GeoCanvas").GeoCanvas} cg The canvas where to draw the layer.
57
+ * @param {import("../core/GeoCanvas.js").GeoCanvas} geoCanvas The canvas where to draw the layer.
56
58
  * @returns {void}
57
59
  */
58
- draw(cg) {
60
+ draw(geoCanvas) {
59
61
  //load data, if not done yet.
60
62
  if (!this.fs) {
61
- this.load(cg.redraw)
63
+ this.load(geoCanvas.redraw)
62
64
  return
63
65
  }
64
66
 
65
67
  //TODO sort lines by width ?
66
68
 
67
- //zoom factor
68
- const zf = cg.getZf()
69
-
70
- //draw in geo coordinates
71
- cg.setCanvasTransform()
69
+ //
70
+ const z = geoCanvas.view.z
72
71
 
73
72
  for (const f of this.fs) {
74
73
  const cs = f.geometry.coordinates
75
74
  if (cs.length < 2) continue
76
75
 
77
76
  //set color
78
- const col = this.color(f, zf)
77
+ const col = this.color(f, z)
79
78
  if (!col || col == 'none') continue
80
- cg.ctx.strokeStyle = col
79
+ geoCanvas.ctx.strokeStyle = col
81
80
 
82
81
  //set linewidth
83
- const wP = this.width(f, zf)
82
+ const wP = this.width(f, z)
84
83
  if (!wP || wP < 0) continue
85
- cg.ctx.lineWidth = wP * zf
84
+ geoCanvas.ctx.lineWidth = wP * z
86
85
 
87
86
  //set line dash
88
- const ldP = this.lineDash(f, zf)
89
- if (ldP) cg.ctx.setLineDash(ldP)
87
+ const ldP = this.lineDash(f, z)
88
+ if (ldP) geoCanvas.ctx.setLineDash(ldP)
90
89
 
91
90
  //draw line
92
- cg.ctx.beginPath()
93
- cg.ctx.moveTo(cs[0][0], cs[0][1])
94
- for (let i = 1; i < cs.length; i++) cg.ctx.lineTo(cs[i][0], cs[i][1])
95
- cg.ctx.stroke()
91
+ geoCanvas.ctx.beginPath()
92
+ geoCanvas.ctx.moveTo(cs[0][0], cs[0][1])
93
+ for (let i = 1; i < cs.length; i++) geoCanvas.ctx.lineTo(cs[i][0], cs[i][1])
94
+ geoCanvas.ctx.stroke()
96
95
  }
97
96
 
98
97
  //...
99
- cg.ctx.setLineDash([])
98
+ geoCanvas.ctx.setLineDash([])
100
99
  }
101
100
 
102
101
  /**
@@ -0,0 +1,140 @@
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ import { Layer } from '../core/Layer.js'
5
+
6
+ /**
7
+ * A layer, which specifies a dataset to be shown with specified styles.
8
+ *
9
+ * @author Joseph Davies, Julien Gaffuri
10
+ */
11
+ export class GridLayer extends Layer {
12
+ /**
13
+ * @param {import("../core/Dataset").Dataset|import("../core/MultiResolutionDataset").MultiResolutionDataset} dataset The dataset to show.
14
+ * @param {Array.<import("../core/Style").Style>} styles The styles, ordered in drawing order.
15
+ * @param {{visible?:function(number):boolean,alpha?:function(number):number,blendOperation?:function(number):GlobalCompositeOperation,minPixelsPerCell?:number,cellInfoHTML?:function(import("../core/Dataset").Cell):string}} opts
16
+ */
17
+ constructor(dataset, styles, opts = {}) {
18
+ super(opts)
19
+ opts = opts || {}
20
+
21
+ /** @type {import("../core/Dataset").Dataset|import("../core/MultiResolutionDataset").MultiResolutionDataset} */
22
+ this.dataset = dataset
23
+ /** @type {Array.<import("../core/Style").Style>} */
24
+ this.styles = styles
25
+
26
+ /**
27
+ * This parameter is used when the dataset is a MultiResolutionDataset.
28
+ * It defines the minimum number of pixels a grid cell should have to select the dataset to display based on its resolution.
29
+ * A low value, means that the map will be more detailled (smaller cells).
30
+ * A high value, means that the map will be less detailled (larger cells).
31
+ * This value should be higher than 1, otherwise it means a grid cell is smaller than the screen resolution.
32
+ * For more complex cell representations that require some more map space, this value should be higher.
33
+ * @type {number} */
34
+ this.minPixelsPerCell = opts.minPixelsPerCell || 3
35
+
36
+ /**
37
+ * The function returning cell information as HTML.
38
+ * This is typically used for tooltip information.
39
+ * @type {function(import("../core/Dataset").Cell, number):string} */
40
+ this.cellInfoHTML = opts.cellInfoHTML || GridLayer.defaultCellInfoHTML
41
+ }
42
+
43
+ /** */
44
+ draw(geoCanvas, legend) {
45
+
46
+ //get zoom level
47
+ const z = geoCanvas.view.z
48
+
49
+ //get layer dataset component
50
+ /** @type {import('../core/Dataset.js').Dataset|undefined} */
51
+ const dsc = this.getDataset(z)
52
+ if (!dsc) return
53
+
54
+ //launch data download, if necessary
55
+ dsc.getData(geoCanvas.extGeo)
56
+
57
+ //update dataset view cache
58
+ dsc.updateViewCache(geoCanvas.extGeo)
59
+
60
+ //draw cells, style by style
61
+ for (const s of this.styles) {
62
+
63
+ //check if style is visible
64
+ if (s.visible && !s.visible(z)) continue
65
+
66
+ //set style alpha and blend mode
67
+ //TODO: multiply by layer alpha ?
68
+ geoCanvas.ctx.globalAlpha = s.alpha ? s.alpha(z) : 1.0
69
+ geoCanvas.ctx.globalCompositeOperation = s.blendOperation(z)
70
+
71
+ //set affin transform to draw with geographical coordinates
72
+ geoCanvas.setCanvasTransform()
73
+
74
+ //draw with style
75
+ s.draw(dsc.getViewCache(), geoCanvas, dsc.getResolution())
76
+
77
+ //draw style filter
78
+ if (s.filterColor)
79
+ s.drawFilter(geoCanvas)
80
+ }
81
+
82
+ //add legend element
83
+ if (legend) {
84
+ for (const s of this.styles) {
85
+ //check if style is visible
86
+ if (s.visible && !s.visible(z)) continue
87
+ for (const lg of s.legends) {
88
+ //console.log(s, lg)
89
+ //this.legend.append(lg.div)
90
+ //s1.node().appendChild(s2.node())
91
+ legend.node().append(lg.div.node())
92
+ }
93
+
94
+ //case for styles of styles, like kernel smoothing
95
+ //TODO do better
96
+ if (s['styles']) {
97
+ for (const s2 of s['styles']) {
98
+ if (s2.visible && !s2.visible(z)) continue
99
+ for (const lg of s2.legends) {
100
+ //console.log(s, lg)
101
+ //this.legend.append(lg.div)
102
+ //s1.node().appendChild(s2.node())
103
+ legend.node().append(lg.div.node())
104
+ }
105
+ }
106
+ }
107
+ }
108
+ }
109
+
110
+ }
111
+
112
+
113
+
114
+ /**
115
+ * Return the relevant dataset component for a specified zoom.
116
+ *
117
+ * @param {number} z
118
+ * @returns {import("../core/Dataset").Dataset|undefined}
119
+ * */
120
+ getDataset(z) {
121
+ return this.dataset.getDataset(z, this.minPixelsPerCell);
122
+ }
123
+
124
+ /**
125
+ * The default function returning cell information as HTML.
126
+ * This is typically used for tooltip information.
127
+ *
128
+ * @param {import("../core/Dataset").Cell} cell
129
+ * @returns {string}
130
+ */
131
+ static defaultCellInfoHTML(cell) {
132
+ const buf = []
133
+ for (const key of Object.keys(cell)) {
134
+ if (key === 'x') continue
135
+ if (key === 'y') continue
136
+ buf.push('<b>', key, '</b>', ' : ', cell[key], '<br>')
137
+ }
138
+ return buf.join('')
139
+ }
140
+ }