gridviz 3.0.26 → 3.0.28

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 +126 -128
  2. package/dist/gridviz.js +8798 -8706
  3. package/dist/gridviz.min.js +1 -1
  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 +544 -544
  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 +78 -77
  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 +224 -214
  28. package/src/layer/GridLayer.js +149 -148
  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/ContourStyle.js +21 -21
  38. package/src/style/DotDensityStyle.js +133 -133
  39. package/src/style/ImageStyle.js +100 -100
  40. package/src/style/IsoFenceStyle.js +217 -217
  41. package/src/style/JoyPlotStyle.js +127 -127
  42. package/src/style/LegoStyle.js +110 -110
  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/ShadingStyle.js +61 -0
  48. package/src/style/ShapeColorSizeStyle.js +147 -147
  49. package/src/style/SideCategoryStyle.js +112 -112
  50. package/src/style/SideStyle.js +212 -212
  51. package/src/style/SquareColorCategoryWebGLStyle.js +107 -107
  52. package/src/style/SquareColorWebGLStyle.js +126 -126
  53. package/src/style/StrokeStyle.js +135 -135
  54. package/src/style/TanakaStyle.js +69 -69
  55. package/src/style/TextStyle.js +110 -110
  56. package/src/style/TimeSeriesStyle.js +222 -222
  57. package/src/utils/WebGLRectangleColoring.js +106 -106
  58. package/src/utils/WebGLSquareColoring.js +118 -118
  59. package/src/utils/WebGLSquareColoringAdvanced.js +230 -230
  60. package/src/utils/WebGLSquareColoringCatAdvanced.js +133 -133
  61. package/src/utils/WebGLSquareColoringKS.js +153 -153
  62. package/src/utils/scale.js +218 -218
  63. package/src/utils/stretching.js +120 -120
  64. package/src/utils/ternary.js +208 -208
  65. package/src/utils/utils.js +58 -58
  66. package/src/utils/webGLUtils.js +72 -72
  67. package/src/utils/zoomUtils.js +142 -142
@@ -1,103 +1,103 @@
1
- import { Button } from './Button.js'
2
-
3
- /**
4
- * Button for toggling fullscreen mode
5
- *
6
- * @module button
7
- * @author Joseph Davies, Julien Gaffuri
8
- */
9
- export class ZoomButtons extends Button {
10
- /**
11
- * @param {Object} opts
12
- */
13
- constructor(opts) {
14
- super(opts)
15
-
16
- this.onZoom = opts.onZoom // custom user event handler
17
- this.delta = opts.delta || 0.2
18
-
19
- // Create zoom in button
20
- this.zoomInBtn = document.createElement('a')
21
- this.zoomInBtn.id = 'zoom-in'
22
- this.zoomInBtn.className = 'gridviz-zoom-button'
23
- this.zoomInBtn.title = 'Zoom in'
24
- this.zoomInBtn.textContent = '+'
25
- this.zoomInBtn.addEventListener('click', (e) => {
26
- this.zoomIn(e)
27
- })
28
- this.zoomInBtn.addEventListener('mouseover', () => {
29
- this.zoomInBtn.style.backgroundColor = 'lightgrey'
30
- })
31
- this.zoomInBtn.addEventListener('mouseout', () => {
32
- this.zoomInBtn.style.backgroundColor = '#ffffff'
33
- })
34
-
35
- // Create zoom out button
36
- this.zoomOutBtn = document.createElement('a')
37
- this.zoomOutBtn.id = 'zoom-out'
38
- this.zoomOutBtn.className = 'gridviz-zoom-button'
39
- this.zoomOutBtn.title = 'Zoom out'
40
- this.zoomOutBtn.textContent = '-'
41
- this.zoomOutBtn.addEventListener('click', (e) => {
42
- this.zoomOut(e)
43
- })
44
- this.zoomOutBtn.addEventListener('mouseover', () => {
45
- this.zoomOutBtn.style.backgroundColor = 'lightgrey'
46
- })
47
- this.zoomOutBtn.addEventListener('mouseout', () => {
48
- this.zoomOutBtn.style.backgroundColor = '#ffffff'
49
- })
50
-
51
- // Set common styles for buttons
52
- const buttons = [this.zoomInBtn, this.zoomOutBtn]
53
- buttons.forEach((btn, index) => {
54
- btn.style.alignItems = 'center'
55
- btn.style.justifyContent = 'center'
56
- btn.style.display = 'flex'
57
- btn.style.border = 'none'
58
- btn.style.color = 'black'
59
- btn.style.textAlign = 'center'
60
- btn.style.textDecoration = 'none'
61
- btn.style.padding = '4px'
62
- btn.style.fontSize = '24px'
63
- btn.style.fontWeight = 'bold'
64
- btn.style.userSelect = 'none'
65
- btn.style.backgroundColor = '#ffffff'
66
- if (index === 0) btn.style.borderBottom = '1px solid grey' // Zoom in button only
67
- })
68
-
69
- // Unset parent class height and display for dual buttons
70
- this.style('height', 'unset')
71
- this.style('display', 'unset')
72
-
73
- // Set position
74
- if (opts.x) {
75
- this.style('left', opts.x + 'px')
76
- } else {
77
- this.style('right', '10px')
78
- }
79
- if (opts.y) {
80
- this.style('top', opts.y + 'px')
81
- } else {
82
- this.style('top', '10px')
83
- }
84
-
85
- // Append buttons to the container
86
- this.div.node().appendChild(this.zoomInBtn)
87
- this.div.node().appendChild(this.zoomOutBtn)
88
- }
89
-
90
- /* Zoom in */
91
- zoomIn(e) {
92
- this.map.setZoom(this.map.getZoom() * (1 - this.delta)).redraw()
93
- if (this.onZoom) this.onZoom(e)
94
- if (this.map.geoCanvas.onZoomFun) this.map.geoCanvas.onZoomFun(e)
95
- }
96
-
97
- /* Zoom out */
98
- zoomOut(e) {
99
- this.map.setZoom(this.map.getZoom() * (1 + this.delta)).redraw()
100
- if (this.onZoom) this.onZoom(e)
101
- if (this.map.geoCanvas.onZoomFun) this.map.geoCanvas.onZoomFun(e)
102
- }
103
- }
1
+ import { Button } from './Button.js'
2
+
3
+ /**
4
+ * Button for toggling fullscreen mode
5
+ *
6
+ * @module button
7
+ * @author Joseph Davies, Julien Gaffuri
8
+ */
9
+ export class ZoomButtons extends Button {
10
+ /**
11
+ * @param {Object} opts
12
+ */
13
+ constructor(opts) {
14
+ super(opts)
15
+
16
+ this.onZoom = opts.onZoom // custom user event handler
17
+ this.delta = opts.delta || 0.2
18
+
19
+ // Create zoom in button
20
+ this.zoomInBtn = document.createElement('a')
21
+ this.zoomInBtn.id = 'zoom-in'
22
+ this.zoomInBtn.className = 'gridviz-zoom-button'
23
+ this.zoomInBtn.title = 'Zoom in'
24
+ this.zoomInBtn.textContent = '+'
25
+ this.zoomInBtn.addEventListener('click', (e) => {
26
+ this.zoomIn(e)
27
+ })
28
+ this.zoomInBtn.addEventListener('mouseover', () => {
29
+ this.zoomInBtn.style.backgroundColor = 'lightgrey'
30
+ })
31
+ this.zoomInBtn.addEventListener('mouseout', () => {
32
+ this.zoomInBtn.style.backgroundColor = '#ffffff'
33
+ })
34
+
35
+ // Create zoom out button
36
+ this.zoomOutBtn = document.createElement('a')
37
+ this.zoomOutBtn.id = 'zoom-out'
38
+ this.zoomOutBtn.className = 'gridviz-zoom-button'
39
+ this.zoomOutBtn.title = 'Zoom out'
40
+ this.zoomOutBtn.textContent = '-'
41
+ this.zoomOutBtn.addEventListener('click', (e) => {
42
+ this.zoomOut(e)
43
+ })
44
+ this.zoomOutBtn.addEventListener('mouseover', () => {
45
+ this.zoomOutBtn.style.backgroundColor = 'lightgrey'
46
+ })
47
+ this.zoomOutBtn.addEventListener('mouseout', () => {
48
+ this.zoomOutBtn.style.backgroundColor = '#ffffff'
49
+ })
50
+
51
+ // Set common styles for buttons
52
+ const buttons = [this.zoomInBtn, this.zoomOutBtn]
53
+ buttons.forEach((btn, index) => {
54
+ btn.style.alignItems = 'center'
55
+ btn.style.justifyContent = 'center'
56
+ btn.style.display = 'flex'
57
+ btn.style.border = 'none'
58
+ btn.style.color = 'black'
59
+ btn.style.textAlign = 'center'
60
+ btn.style.textDecoration = 'none'
61
+ btn.style.padding = '4px'
62
+ btn.style.fontSize = '24px'
63
+ btn.style.fontWeight = 'bold'
64
+ btn.style.userSelect = 'none'
65
+ btn.style.backgroundColor = '#ffffff'
66
+ if (index === 0) btn.style.borderBottom = '1px solid grey' // Zoom in button only
67
+ })
68
+
69
+ // Unset parent class height and display for dual buttons
70
+ this.style('height', 'unset')
71
+ this.style('display', 'unset')
72
+
73
+ // Set position
74
+ if (opts.x) {
75
+ this.style('left', opts.x + 'px')
76
+ } else {
77
+ this.style('right', '10px')
78
+ }
79
+ if (opts.y) {
80
+ this.style('top', opts.y + 'px')
81
+ } else {
82
+ this.style('top', '10px')
83
+ }
84
+
85
+ // Append buttons to the container
86
+ this.div.node().appendChild(this.zoomInBtn)
87
+ this.div.node().appendChild(this.zoomOutBtn)
88
+ }
89
+
90
+ /* Zoom in */
91
+ zoomIn(e) {
92
+ this.map.setZoom(this.map.getZoom() * (1 - this.delta)).redraw()
93
+ if (this.onZoom) this.onZoom(e)
94
+ if (this.map.geoCanvas.onZoomFun) this.map.geoCanvas.onZoomFun(e)
95
+ }
96
+
97
+ /* Zoom out */
98
+ zoomOut(e) {
99
+ this.map.setZoom(this.map.getZoom() * (1 + this.delta)).redraw()
100
+ if (this.onZoom) this.onZoom(e)
101
+ if (this.map.geoCanvas.onZoomFun) this.map.geoCanvas.onZoomFun(e)
102
+ }
103
+ }
@@ -1,154 +1,154 @@
1
- //@ts-check
2
- 'use strict'
3
-
4
- /**
5
- * A grid cell.
6
- * @typedef {{x: number, y: number}} Cell */
7
-
8
- /**
9
- * A dataset component, of grid cells.
10
- * @abstract
11
- *
12
- * @module core
13
- * @author Joseph Davies, Julien Gaffuri
14
- */
15
- export class Dataset {
16
- /**
17
- * @param {import("./Map.js").Map} map The map.
18
- * @param {string} url The URL of the dataset.
19
- * @param {number} resolution The dataset resolution, in the CRS geographical unit.
20
- * @param {{preprocess?:function(Cell):boolean, mixedResolution?:function(Cell):number}} opts
21
- * @abstract
22
- */
23
- constructor(map, url, resolution, opts = {}) {
24
- /**
25
- * The map.
26
- * @protected
27
- * @type {import("./Map.js").Map} */
28
- this.map = map
29
-
30
- /**
31
- * The url of the dataset.
32
- * @protected
33
- * @type {string} */
34
- this.url = url
35
-
36
- /**
37
- * The dataset resolution in geographical unit.
38
- * @protected
39
- * @type {number} */
40
- this.resolution = resolution
41
-
42
- /**
43
- * In case the dataset is a dataset with cells having different resolution,
44
- * this is the function returning the resolution of each cell.
45
- * @protected
46
- * @type {(function(Cell):number )| undefined } */
47
- this.mixedResolution = opts.mixedResolution
48
-
49
- /**
50
- * A preprocess to run on each cell after loading. It can be used to apply some specific treatment before or compute a new column. And also to determine which cells to keep after loading.
51
- * @type {(function(Cell):boolean )| undefined } */
52
- this.preprocess = opts.preprocess || undefined
53
-
54
- /** The cells within the view
55
- * @protected
56
- * @type {Array.<Cell>} */
57
- this.cellsViewCache = []
58
- }
59
-
60
- /**
61
- * Request data within a geographic envelope.
62
- *
63
- * @abstract
64
- * @param {import("./GeoCanvas").Envelope|undefined} extGeo
65
- * @returns {this}
66
- */
67
- getData(extGeo = undefined) {
68
- throw new Error('Method getData not implemented.')
69
- }
70
-
71
- /**
72
- * Fill the view cache with all cells which are within a geographical envelope.
73
- * @abstract
74
- * @param {import("./GeoCanvas").Envelope} extGeo The view geographical envelope.
75
- * @returns {void}
76
- */
77
- updateViewCache(extGeo) {
78
- throw new Error('Method updateViewCache not implemented.')
79
- }
80
-
81
- /**
82
- * Get a cell under a given position, if any.
83
- *
84
- * @param {{x:number,y:number}} posGeo
85
- * @param {Array.<Cell>} cells Some cells from the dataset (a subset if necessary, usually the view cache).
86
- * @returns {Cell|undefined}
87
- */
88
- getCellFromPosition(posGeo, cells) {
89
- //compute candidate cell position
90
- /** @type {number} */
91
- //const r = this.getResolution()
92
- /** @type {number} */
93
- //const cellX = r * Math.floor(posGeo.x / r)
94
- /** @type {number} */
95
- //const cellY = r * Math.floor(posGeo.y / r)
96
-
97
- /*/get cell
98
- for (const cell of cells) {
99
- if (cell.x != cellX) continue
100
- if (cell.y != cellY) continue
101
- return cell
102
- }
103
- return undefined*/
104
-
105
- //rare case of mixed resolution dataset
106
- if (this.mixedResolution) {
107
- for (const c of cells) {
108
- /** @type {number} */
109
- const r = +this.mixedResolution(c)
110
- if (posGeo.x < c.x) continue
111
- else if (c.x + r < posGeo.x) continue
112
- else if (posGeo.y < c.y) continue
113
- else if (c.y + r < posGeo.y) continue
114
- else return c
115
- }
116
- return undefined
117
- }
118
-
119
- //common case
120
-
121
- /** @type {number} */
122
- const r = this.getResolution()
123
- for (const cell of cells) {
124
- if (posGeo.x < cell.x) continue
125
- else if (cell.x + r < posGeo.x) continue
126
- else if (posGeo.y < cell.y) continue
127
- else if (cell.y + r < posGeo.y) continue
128
- else return cell
129
- }
130
- return undefined
131
- }
132
-
133
- //getters and setters
134
-
135
- /** @returns {number} */
136
- getResolution() {
137
- return this.resolution
138
- }
139
-
140
- /** @returns {Array.<Cell>} */
141
- getViewCache() {
142
- return this.cellsViewCache
143
- }
144
-
145
- /**
146
- * Return the relevant dataset for a specified zoom.
147
- * @param {number} z
148
- * @param {number} minPixelsPerCell
149
- * @returns {Dataset|undefined}
150
- * */
151
- getDataset(z, minPixelsPerCell) {
152
- return this
153
- }
154
- }
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ /**
5
+ * A grid cell.
6
+ * @typedef {{x: number, y: number}} Cell */
7
+
8
+ /**
9
+ * A dataset component, of grid cells.
10
+ * @abstract
11
+ *
12
+ * @module core
13
+ * @author Joseph Davies, Julien Gaffuri
14
+ */
15
+ export class Dataset {
16
+ /**
17
+ * @param {import("./Map.js").Map} map The map.
18
+ * @param {string} url The URL of the dataset.
19
+ * @param {number} resolution The dataset resolution, in the CRS geographical unit.
20
+ * @param {{preprocess?:function(Cell):boolean, mixedResolution?:function(Cell):number}} opts
21
+ * @abstract
22
+ */
23
+ constructor(map, url, resolution, opts = {}) {
24
+ /**
25
+ * The map.
26
+ * @protected
27
+ * @type {import("./Map.js").Map} */
28
+ this.map = map
29
+
30
+ /**
31
+ * The url of the dataset.
32
+ * @protected
33
+ * @type {string} */
34
+ this.url = url
35
+
36
+ /**
37
+ * The dataset resolution in geographical unit.
38
+ * @protected
39
+ * @type {number} */
40
+ this.resolution = resolution
41
+
42
+ /**
43
+ * In case the dataset is a dataset with cells having different resolution,
44
+ * this is the function returning the resolution of each cell.
45
+ * @protected
46
+ * @type {(function(Cell):number )| undefined } */
47
+ this.mixedResolution = opts.mixedResolution
48
+
49
+ /**
50
+ * A preprocess to run on each cell after loading. It can be used to apply some specific treatment before or compute a new column. And also to determine which cells to keep after loading.
51
+ * @type {(function(Cell):boolean )| undefined } */
52
+ this.preprocess = opts.preprocess || undefined
53
+
54
+ /** The cells within the view
55
+ * @protected
56
+ * @type {Array.<Cell>} */
57
+ this.cellsViewCache = []
58
+ }
59
+
60
+ /**
61
+ * Request data within a geographic envelope.
62
+ *
63
+ * @abstract
64
+ * @param {import("./GeoCanvas").Envelope|undefined} extGeo
65
+ * @returns {this}
66
+ */
67
+ getData(extGeo = undefined) {
68
+ throw new Error('Method getData not implemented.')
69
+ }
70
+
71
+ /**
72
+ * Fill the view cache with all cells which are within a geographical envelope.
73
+ * @abstract
74
+ * @param {import("./GeoCanvas").Envelope} extGeo The view geographical envelope.
75
+ * @returns {void}
76
+ */
77
+ updateViewCache(extGeo) {
78
+ throw new Error('Method updateViewCache not implemented.')
79
+ }
80
+
81
+ /**
82
+ * Get a cell under a given position, if any.
83
+ *
84
+ * @param {{x:number,y:number}} posGeo
85
+ * @param {Array.<Cell>} cells Some cells from the dataset (a subset if necessary, usually the view cache).
86
+ * @returns {Cell|undefined}
87
+ */
88
+ getCellFromPosition(posGeo, cells) {
89
+ //compute candidate cell position
90
+ /** @type {number} */
91
+ //const r = this.getResolution()
92
+ /** @type {number} */
93
+ //const cellX = r * Math.floor(posGeo.x / r)
94
+ /** @type {number} */
95
+ //const cellY = r * Math.floor(posGeo.y / r)
96
+
97
+ /*/get cell
98
+ for (const cell of cells) {
99
+ if (cell.x != cellX) continue
100
+ if (cell.y != cellY) continue
101
+ return cell
102
+ }
103
+ return undefined*/
104
+
105
+ //rare case of mixed resolution dataset
106
+ if (this.mixedResolution) {
107
+ for (const c of cells) {
108
+ /** @type {number} */
109
+ const r = +this.mixedResolution(c)
110
+ if (posGeo.x < c.x) continue
111
+ else if (c.x + r < posGeo.x) continue
112
+ else if (posGeo.y < c.y) continue
113
+ else if (c.y + r < posGeo.y) continue
114
+ else return c
115
+ }
116
+ return undefined
117
+ }
118
+
119
+ //common case
120
+
121
+ /** @type {number} */
122
+ const r = this.getResolution()
123
+ for (const cell of cells) {
124
+ if (posGeo.x < cell.x) continue
125
+ else if (cell.x + r < posGeo.x) continue
126
+ else if (posGeo.y < cell.y) continue
127
+ else if (cell.y + r < posGeo.y) continue
128
+ else return cell
129
+ }
130
+ return undefined
131
+ }
132
+
133
+ //getters and setters
134
+
135
+ /** @returns {number} */
136
+ getResolution() {
137
+ return this.resolution
138
+ }
139
+
140
+ /** @returns {Array.<Cell>} */
141
+ getViewCache() {
142
+ return this.cellsViewCache
143
+ }
144
+
145
+ /**
146
+ * Return the relevant dataset for a specified zoom.
147
+ * @param {number} z
148
+ * @param {number} minPixelsPerCell
149
+ * @returns {Dataset|undefined}
150
+ * */
151
+ getDataset(z, minPixelsPerCell) {
152
+ return this
153
+ }
154
+ }
@@ -1,78 +1,78 @@
1
- //@ts-check
2
- 'use strict'
3
-
4
- /**
5
- * This is an abstract class used to group elements shared between Layer and Style classes.
6
- *
7
- * @abstract
8
- * @module core
9
- * @author Joseph Davies, Julien Gaffuri
10
- */
11
- export class Drawable {
12
- /**
13
- * @param {object} opts
14
- */
15
- constructor(opts) {
16
- opts = opts || {}
17
-
18
- /** A function specifying if the element should be visible or not.
19
- * The function parameter is the zoom level.
20
- * @type {function(number):boolean} */
21
- this.visible = opts.visible
22
-
23
- /** A function returning the alpha (transparency/opacity), between 0.0 (fully transparent) and 1.0 (fully opaque).
24
- * The function parameter is the zoom level.
25
- * (see CanvasRenderingContext2D: globalAlpha property)
26
- * @type {(function(number):number)|undefined} */
27
- this.alpha = opts.alpha
28
-
29
- /** A function returning the blend operation.
30
- * The function parameter is the zoom level.
31
- * (see CanvasRenderingContext2D: globalCompositeOperation property)
32
- * @type {function(number):GlobalCompositeOperation} */
33
- this.blendOperation = opts.blendOperation || ((z) => 'source-over')
34
-
35
- /** @type {(function(number):string)|undefined} */
36
- this.filterColor = opts.filterColor // (z) => "#eee7"
37
- /** @type {(function(number):GlobalCompositeOperation|"none")|undefined} */
38
- this.filterBlendOperation = opts.filterBlendOperation // (z) => "multiply"
39
- }
40
-
41
- /**
42
- * Draw layer filter.
43
- *
44
- * @param {import("./GeoCanvas.js").GeoCanvas} geoCanvas The canvas where to draw the layer.
45
- * @returns {void}
46
- * @abstract
47
- */
48
- drawFilter(geoCanvas) {
49
- //no filter: return
50
- if (!this.filterColor) return
51
-
52
- //get filter
53
- const fc = this.filterColor(geoCanvas.view.z)
54
-
55
- //no filter: return
56
- if (!fc || fc == 'none') return
57
-
58
- //draw filter
59
-
60
- //set color
61
- geoCanvas.offscreenCtx.fillStyle = fc
62
-
63
- //save blend mode and set new, if any
64
- let bo = undefined, bo2 = undefined
65
- if (this.filterBlendOperation) {
66
- bo = geoCanvas.offscreenCtx.globalCompositeOperation
67
- bo2 = this.filterBlendOperation(geoCanvas.view.z)
68
- }
69
- if (bo2 && bo2 != "none") geoCanvas.offscreenCtx.globalCompositeOperation = bo2;
70
-
71
- //draw
72
- geoCanvas.offscreenCtx.fillRect(0, 0, geoCanvas.w, geoCanvas.h)
73
-
74
- //restore blend mode
75
- if (bo) geoCanvas.offscreenCtx.globalCompositeOperation = bo;
76
-
77
- }
78
- }
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ /**
5
+ * This is an abstract class used to group elements shared between Layer and Style classes.
6
+ *
7
+ * @abstract
8
+ * @module core
9
+ * @author Joseph Davies, Julien Gaffuri
10
+ */
11
+ export class Drawable {
12
+ /**
13
+ * @param {object} opts
14
+ */
15
+ constructor(opts) {
16
+ opts = opts || {}
17
+
18
+ /** A function specifying if the element should be visible or not.
19
+ * The function parameter is the zoom level.
20
+ * @type {function(number):boolean} */
21
+ this.visible = opts.visible
22
+
23
+ /** A function returning the alpha (transparency/opacity), between 0.0 (fully transparent) and 1.0 (fully opaque).
24
+ * The function parameter is the zoom level.
25
+ * (see CanvasRenderingContext2D: globalAlpha property)
26
+ * @type {(function(number):number)|undefined} */
27
+ this.alpha = opts.alpha
28
+
29
+ /** A function returning the blend operation.
30
+ * The function parameter is the zoom level.
31
+ * (see CanvasRenderingContext2D: globalCompositeOperation property)
32
+ * @type {function(number):GlobalCompositeOperation} */
33
+ this.blendOperation = opts.blendOperation || ((z) => 'source-over')
34
+
35
+ /** @type {(function(number):string)|undefined} */
36
+ this.filterColor = opts.filterColor // (z) => "#eee7"
37
+ /** @type {(function(number):GlobalCompositeOperation|"none")|undefined} */
38
+ this.filterBlendOperation = opts.filterBlendOperation // (z) => "multiply"
39
+ }
40
+
41
+ /**
42
+ * Draw layer filter.
43
+ *
44
+ * @param {import("./GeoCanvas.js").GeoCanvas} geoCanvas The canvas where to draw the layer.
45
+ * @returns {void}
46
+ * @abstract
47
+ */
48
+ drawFilter(geoCanvas) {
49
+ //no filter: return
50
+ if (!this.filterColor) return
51
+
52
+ //get filter
53
+ const fc = this.filterColor(geoCanvas.view.z)
54
+
55
+ //no filter: return
56
+ if (!fc || fc == 'none') return
57
+
58
+ //draw filter
59
+
60
+ //set color
61
+ geoCanvas.offscreenCtx.fillStyle = fc
62
+
63
+ //save blend mode and set new, if any
64
+ let bo = undefined, bo2 = undefined
65
+ if (this.filterBlendOperation) {
66
+ bo = geoCanvas.offscreenCtx.globalCompositeOperation
67
+ bo2 = this.filterBlendOperation(geoCanvas.view.z)
68
+ }
69
+ if (bo2 && bo2 != "none") geoCanvas.offscreenCtx.globalCompositeOperation = bo2;
70
+
71
+ //draw
72
+ geoCanvas.offscreenCtx.fillRect(0, 0, geoCanvas.w, geoCanvas.h)
73
+
74
+ //restore blend mode
75
+ if (bo) geoCanvas.offscreenCtx.globalCompositeOperation = bo;
76
+
77
+ }
78
+ }