gridviz 3.0.19 → 3.0.20

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 +128 -128
  2. package/dist/gridviz.js +7861 -7861
  3. package/dist/gridviz.min.js +1 -1
  4. package/package.json +74 -74
  5. package/src/button/ZoomButtons.js +101 -101
  6. package/src/core/Dataset.js +154 -154
  7. package/src/core/Drawable.js +60 -60
  8. package/src/core/GeoCanvas.js +430 -430
  9. package/src/core/Layer.js +23 -23
  10. package/src/core/Legend.js +108 -108
  11. package/src/core/Map.js +516 -516
  12. package/src/core/MultiResolutionDataset.js +93 -93
  13. package/src/core/Style.js +98 -98
  14. package/src/dataset/CSVGrid.js +112 -112
  15. package/src/dataset/GeoTIFF.js +122 -122
  16. package/src/dataset/JSGrid.js +55 -55
  17. package/src/dataset/TiledGrid.js +302 -302
  18. package/src/dataset/worker.js +18 -18
  19. package/src/index.js +77 -77
  20. package/src/layer/BackgroundLayer.js +162 -162
  21. package/src/layer/BackgroundLayerImage.js +81 -81
  22. package/src/layer/BackgroundLayerWMS.js +104 -104
  23. package/src/layer/GeoJSONLayer.js +214 -214
  24. package/src/layer/GridLayer.js +148 -148
  25. package/src/layer/LabelLayer.js +194 -194
  26. package/src/legend/ColorCategoryLegend.js +109 -109
  27. package/src/legend/ColorDiscreteLegend.js +100 -100
  28. package/src/legend/ColorLegend.js +115 -115
  29. package/src/legend/OrientationLegend.js +89 -89
  30. package/src/legend/SizeLegend.js +224 -224
  31. package/src/legend/TernaryLegend.js +302 -302
  32. package/src/style/CompositionStyle.js +291 -291
  33. package/src/style/DotDensityStyle.js +133 -133
  34. package/src/style/ImageStyle.js +100 -100
  35. package/src/style/IsoFenceStyle.js +217 -217
  36. package/src/style/JoyPlotStyle.js +127 -127
  37. package/src/style/LegoStyle.js +110 -110
  38. package/src/style/MosaicStyle.js +99 -99
  39. package/src/style/NinjaStarStyle.js +102 -102
  40. package/src/style/PillarStyle.js +207 -207
  41. package/src/style/SegmentStyle.js +105 -105
  42. package/src/style/ShapeColorSizeStyle.js +147 -147
  43. package/src/style/SideCategoryStyle.js +112 -112
  44. package/src/style/SideStyle.js +212 -212
  45. package/src/style/SquareColorCategoryWebGLStyle.js +107 -107
  46. package/src/style/SquareColorWebGLStyle.js +126 -126
  47. package/src/style/StrokeStyle.js +135 -135
  48. package/src/style/TanakaStyle.js +69 -69
  49. package/src/style/TextStyle.js +110 -110
  50. package/src/style/TimeSeriesStyle.js +222 -222
  51. package/src/utils/scale.js +218 -218
  52. package/src/utils/stretching.js +120 -120
  53. package/src/utils/ternary.js +208 -208
  54. package/src/utils/utils.js +58 -58
  55. package/src/utils/webGLUtils.js +72 -72
@@ -1,291 +1,291 @@
1
- //@ts-check
2
- 'use strict'
3
-
4
- import { Style } from '../core/Style.js'
5
-
6
- /** @typedef {"flag"|"piechart"|"ring"|"segment"|"radar"|"agepyramid"|"halftone"} CompositionType */
7
-
8
- /**
9
- * A style showing the composition of a total in different categories, with different color hues.
10
- * It consists of a symbol with different parts, whose size reflect the proportion of the corresponding category.
11
- * For a list of supported symbols, @see CompositionType
12
- * The symbol can be scaled depending on the cell importance.
13
- *
14
- * @module style
15
- * @author Julien Gaffuri
16
- */
17
- export class CompositionStyle extends Style {
18
- /** @param {object} opts */
19
- constructor(opts) {
20
- super(opts)
21
- opts = opts || {}
22
-
23
- /**
24
- * The dictionary (string -> color) which give the color of each category.
25
- * @type {object} */
26
- this.color = opts.color
27
-
28
- /**
29
- * A function returning the type of decomposition symbol of a cell, @see CompositionType
30
- * @type {function(import("../core/Dataset.js").Cell,number, number,object):CompositionType} */
31
- this.type = opts.type || (() => 'flag') //(c,r,z,vs) => {}
32
-
33
- /** A function returning the size of a cell in geographical unit.
34
- * @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
35
- this.size = opts.size || ((c, r) => r) //(c,r,z,vs) => {}
36
-
37
- /** For style types with stripes (flag, segment), the orientation of the stripes (0 for horizontal, other for vertical).
38
- * @type {function(import("../core/Dataset.js").Cell,number,number,object):number} */
39
- this.stripesOrientation = opts.stripesOrientation || (() => 0) //(c,r,z,vs) => ...
40
-
41
- /** The function specifying an offset angle for a radar, halftone or pie chart style.
42
- * The angle is specified in degree. The rotation is anti-clockwise.
43
- * @type {function(import("../core/Dataset.js").Cell,number,number,object):number} */
44
- this.offsetAngle = opts.offsetAngle || (() => 0) //(c,r,z,vs) => ...
45
-
46
- /** The function specifying the height of the age pyramid, in geo unit.
47
- * @type {function(import("../core/Dataset.js").Cell,number,number,object):number} */
48
- this.agePyramidHeight = opts.agePyramidHeight || ((c, r) => r) //(c,r,z,vs) => ...
49
-
50
- /** For pie chart, this is parameter for internal radius, so that the pie chart looks like a donut.
51
- * 0 for normal pie charts, 0.5 to empty half of the radius.
52
- * @type {number} */
53
- this.pieChartInternalRadiusFactor = opts.pieChartInternalRadiusFactor || 0
54
- }
55
-
56
- /**
57
- * Draw cells as squares depending on their value.
58
- *
59
- * @param {Array.<import("../core/Dataset.js").Cell>} cells
60
- * @param {import("../core/GeoCanvas.js").GeoCanvas} geoCanvas
61
- * @param {number} resolution
62
- */
63
- draw(cells, geoCanvas, resolution) {
64
- //filter
65
- if (this.filter) cells = cells.filter(this.filter)
66
-
67
- //
68
- const z = geoCanvas.view.z
69
- const ctx = geoCanvas.offscreenCtx
70
-
71
- //get view scale
72
- const viewScale = this.viewScale ? this.viewScale(cells, resolution, z) : undefined
73
-
74
- //nb categories - used for radar and agepyramid
75
- const nbCat = Object.entries(this.color).length
76
-
77
- //draw calls
78
- for (let cell of cells) {
79
- //size
80
- const sG = this.size ? this.size(cell, resolution, z, viewScale) : resolution
81
- if (!sG) continue
82
-
83
- //get offset
84
- const offset = this.offset(cell, resolution, z)
85
-
86
- //get symbol type
87
- const type_ = this.type ? this.type(cell, resolution, z, viewScale) : 'flag'
88
-
89
- //compute center position
90
- const xc = cell.x + offset.dx + (type_ === 'agepyramid' ? 0 : resolution * 0.5)
91
- const yc = cell.y + offset.dy + (type_ === 'agepyramid' ? 0 : resolution * 0.5)
92
-
93
- //compute offset angle, when relevant
94
- const offAng = this.offsetAngle
95
- ? (this.offsetAngle(cell, resolution, z, viewScale) * Math.PI) / 180
96
- : 0
97
-
98
- if (type_ === 'agepyramid' || type_ === 'radar' || type_ === 'halftone') {
99
- //get cell category max value
100
- let maxVal = -Infinity
101
- for (let key of Object.keys(this.color)) {
102
- const v = +cell[key]
103
- if (v > maxVal) maxVal = v
104
- }
105
-
106
- //cumul
107
- let cumul = 0
108
- if (type_ === 'agepyramid' && this.agePyramidHeight)
109
- cumul = (resolution - this.agePyramidHeight(cell, resolution, z, viewScale)) / 2
110
- if (type_ === 'radar' || type_ === 'halftone') cumul = Math.PI / 2 + offAng
111
-
112
- //compute the increment, which is the value to increment the cumul for each category
113
- const incr =
114
- type_ === 'agepyramid'
115
- ? (this.agePyramidHeight
116
- ? this.agePyramidHeight(cell, resolution, z, viewScale)
117
- : resolution) / nbCat
118
- : type_ === 'radar' || type_ === 'halftone'
119
- ? (2 * Math.PI) / nbCat
120
- : undefined
121
- if (incr === undefined) throw new Error('Unexpected symbol type:' + type_)
122
-
123
- for (let [column, color] of Object.entries(this.color)) {
124
- if (type_ === 'agepyramid') {
125
- //set category color
126
- ctx.fillStyle = color
127
-
128
- //get category value
129
- const val = cell[column]
130
-
131
- //compute category length - in geo
132
- /** @type {number} */
133
- const wG = (sG * val) / maxVal
134
-
135
- //draw bar
136
- ctx.fillRect(xc + (resolution - wG) / 2, yc + cumul, wG, incr)
137
-
138
- //next height
139
- cumul += incr
140
- } else if (type_ === 'radar') {
141
- //set category color
142
- ctx.fillStyle = color
143
-
144
- //get categroy value
145
- const val = cell[column]
146
-
147
- //compute category radius - in geo
148
- /** @type {number} */
149
- //const rG = this.radius(val, r, stat, cellStat, z)
150
- const rG = (sG / 2) * Math.sqrt(val / maxVal)
151
-
152
- //draw angular sector
153
- ctx.beginPath()
154
- ctx.moveTo(xc, yc)
155
- ctx.arc(xc, yc, rG, cumul - incr, cumul)
156
- ctx.lineTo(xc, yc)
157
- ctx.fill()
158
-
159
- //next angular sector
160
- cumul += incr
161
- } else if (type_ === 'halftone') {
162
- //set category color
163
- ctx.fillStyle = color
164
-
165
- //get categroy value
166
- const val = cell[column]
167
-
168
- //compute category radius - in geo
169
- /** @type {number} */
170
- const rG = sG * 0.333 * Math.sqrt(val / maxVal)
171
-
172
- //draw circle
173
- ctx.beginPath()
174
- ctx.arc(
175
- xc + resolution * 0.25 * Math.cos(cumul),
176
- yc + resolution * 0.25 * Math.sin(cumul),
177
- rG,
178
- 0,
179
- 2 * Math.PI
180
- )
181
- ctx.fill()
182
-
183
- //next angular sector
184
- cumul += incr
185
- } else {
186
- throw new Error('Unexpected symbol type:' + type_)
187
- }
188
- }
189
- } else {
190
- //compute total
191
- let total = 0
192
- for (let column of Object.keys(this.color)) {
193
- const v = +cell[column]
194
- if (!v) continue
195
- total += v
196
- }
197
- if (!total || isNaN(total)) continue
198
-
199
- //draw decomposition symbol
200
- let cumul = 0
201
- const d = resolution * (1 - sG / resolution) * 0.5
202
- const ori = this.stripesOrientation(cell, resolution, z, viewScale)
203
-
204
- for (let [column, color] of Object.entries(this.color)) {
205
- //get share
206
- const share = cell[column] / total
207
- if (!share || isNaN(share)) continue
208
-
209
- //set color
210
- ctx.fillStyle = color
211
-
212
- //draw symbol part
213
- if (type_ === 'flag') {
214
- //draw flag stripe
215
- if (ori == 0) {
216
- //horizontal
217
- ctx.fillRect(
218
- cell.x + d + offset.dx,
219
- cell.y + d + cumul * sG + offset.dy,
220
- sG,
221
- share * sG
222
- )
223
- } else {
224
- //vertical
225
- ctx.fillRect(
226
- cell.x + d + cumul * sG + offset.dx,
227
- cell.y + d + offset.dy,
228
- share * sG,
229
- sG
230
- )
231
- }
232
- } else if (type_ === 'piechart') {
233
- //draw pie chart angular sector
234
-
235
- //compute angles
236
- const a1 = cumul * 2 * Math.PI
237
- const a2 = (cumul + share) * 2 * Math.PI
238
-
239
- //draw
240
- ctx.beginPath()
241
- ctx.moveTo(xc, yc)
242
- ctx.arc(xc, yc, sG * 0.5, a1 + offAng, a2 + offAng)
243
- if (this.pieChartInternalRadiusFactor)
244
- ctx.arc(
245
- xc,
246
- yc,
247
- sG * 0.5 * this.pieChartInternalRadiusFactor,
248
- a1 + offAng,
249
- a2 + offAng,
250
- true
251
- )
252
- ctx.closePath()
253
- ctx.fill()
254
- } else if (type_ === 'ring') {
255
- //draw ring
256
- ctx.beginPath()
257
- ctx.arc(xc, yc, Math.sqrt(1 - cumul) * sG * 0.5, 0, 2 * Math.PI)
258
- ctx.fill()
259
- } else if (type_ === 'segment') {
260
- //draw segment sections
261
- const wG = (sG * sG) / resolution
262
- if (ori == 0) {
263
- //horizontal
264
- ctx.fillRect(
265
- cell.x + offset.dx,
266
- cell.y + (resolution - wG) / 2 + cumul * wG + offset.dy,
267
- resolution,
268
- share * wG
269
- )
270
- } else {
271
- //vertical
272
- ctx.fillRect(
273
- cell.x + cumul * resolution + offset.dx,
274
- cell.y + (resolution - wG) / 2 + offset.dy,
275
- share * resolution,
276
- wG
277
- )
278
- }
279
- } else {
280
- throw new Error('Unexpected symbol type:' + type_)
281
- }
282
-
283
- cumul += share
284
- }
285
- }
286
- }
287
-
288
- //update legends
289
- this.updateLegends({ style: this, resolution: resolution, z: z, viewScale: viewScale })
290
- }
291
- }
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ import { Style } from '../core/Style.js'
5
+
6
+ /** @typedef {"flag"|"piechart"|"ring"|"segment"|"radar"|"agepyramid"|"halftone"} CompositionType */
7
+
8
+ /**
9
+ * A style showing the composition of a total in different categories, with different color hues.
10
+ * It consists of a symbol with different parts, whose size reflect the proportion of the corresponding category.
11
+ * For a list of supported symbols, @see CompositionType
12
+ * The symbol can be scaled depending on the cell importance.
13
+ *
14
+ * @module style
15
+ * @author Julien Gaffuri
16
+ */
17
+ export class CompositionStyle extends Style {
18
+ /** @param {object} opts */
19
+ constructor(opts) {
20
+ super(opts)
21
+ opts = opts || {}
22
+
23
+ /**
24
+ * The dictionary (string -> color) which give the color of each category.
25
+ * @type {object} */
26
+ this.color = opts.color
27
+
28
+ /**
29
+ * A function returning the type of decomposition symbol of a cell, @see CompositionType
30
+ * @type {function(import("../core/Dataset.js").Cell,number, number,object):CompositionType} */
31
+ this.type = opts.type || (() => 'flag') //(c,r,z,vs) => {}
32
+
33
+ /** A function returning the size of a cell in geographical unit.
34
+ * @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
35
+ this.size = opts.size || ((c, r) => r) //(c,r,z,vs) => {}
36
+
37
+ /** For style types with stripes (flag, segment), the orientation of the stripes (0 for horizontal, other for vertical).
38
+ * @type {function(import("../core/Dataset.js").Cell,number,number,object):number} */
39
+ this.stripesOrientation = opts.stripesOrientation || (() => 0) //(c,r,z,vs) => ...
40
+
41
+ /** The function specifying an offset angle for a radar, halftone or pie chart style.
42
+ * The angle is specified in degree. The rotation is anti-clockwise.
43
+ * @type {function(import("../core/Dataset.js").Cell,number,number,object):number} */
44
+ this.offsetAngle = opts.offsetAngle || (() => 0) //(c,r,z,vs) => ...
45
+
46
+ /** The function specifying the height of the age pyramid, in geo unit.
47
+ * @type {function(import("../core/Dataset.js").Cell,number,number,object):number} */
48
+ this.agePyramidHeight = opts.agePyramidHeight || ((c, r) => r) //(c,r,z,vs) => ...
49
+
50
+ /** For pie chart, this is parameter for internal radius, so that the pie chart looks like a donut.
51
+ * 0 for normal pie charts, 0.5 to empty half of the radius.
52
+ * @type {number} */
53
+ this.pieChartInternalRadiusFactor = opts.pieChartInternalRadiusFactor || 0
54
+ }
55
+
56
+ /**
57
+ * Draw cells as squares depending on their value.
58
+ *
59
+ * @param {Array.<import("../core/Dataset.js").Cell>} cells
60
+ * @param {import("../core/GeoCanvas.js").GeoCanvas} geoCanvas
61
+ * @param {number} resolution
62
+ */
63
+ draw(cells, geoCanvas, resolution) {
64
+ //filter
65
+ if (this.filter) cells = cells.filter(this.filter)
66
+
67
+ //
68
+ const z = geoCanvas.view.z
69
+ const ctx = geoCanvas.offscreenCtx
70
+
71
+ //get view scale
72
+ const viewScale = this.viewScale ? this.viewScale(cells, resolution, z) : undefined
73
+
74
+ //nb categories - used for radar and agepyramid
75
+ const nbCat = Object.entries(this.color).length
76
+
77
+ //draw calls
78
+ for (let cell of cells) {
79
+ //size
80
+ const sG = this.size ? this.size(cell, resolution, z, viewScale) : resolution
81
+ if (!sG) continue
82
+
83
+ //get offset
84
+ const offset = this.offset(cell, resolution, z)
85
+
86
+ //get symbol type
87
+ const type_ = this.type ? this.type(cell, resolution, z, viewScale) : 'flag'
88
+
89
+ //compute center position
90
+ const xc = cell.x + offset.dx + (type_ === 'agepyramid' ? 0 : resolution * 0.5)
91
+ const yc = cell.y + offset.dy + (type_ === 'agepyramid' ? 0 : resolution * 0.5)
92
+
93
+ //compute offset angle, when relevant
94
+ const offAng = this.offsetAngle
95
+ ? (this.offsetAngle(cell, resolution, z, viewScale) * Math.PI) / 180
96
+ : 0
97
+
98
+ if (type_ === 'agepyramid' || type_ === 'radar' || type_ === 'halftone') {
99
+ //get cell category max value
100
+ let maxVal = -Infinity
101
+ for (let key of Object.keys(this.color)) {
102
+ const v = +cell[key]
103
+ if (v > maxVal) maxVal = v
104
+ }
105
+
106
+ //cumul
107
+ let cumul = 0
108
+ if (type_ === 'agepyramid' && this.agePyramidHeight)
109
+ cumul = (resolution - this.agePyramidHeight(cell, resolution, z, viewScale)) / 2
110
+ if (type_ === 'radar' || type_ === 'halftone') cumul = Math.PI / 2 + offAng
111
+
112
+ //compute the increment, which is the value to increment the cumul for each category
113
+ const incr =
114
+ type_ === 'agepyramid'
115
+ ? (this.agePyramidHeight
116
+ ? this.agePyramidHeight(cell, resolution, z, viewScale)
117
+ : resolution) / nbCat
118
+ : type_ === 'radar' || type_ === 'halftone'
119
+ ? (2 * Math.PI) / nbCat
120
+ : undefined
121
+ if (incr === undefined) throw new Error('Unexpected symbol type:' + type_)
122
+
123
+ for (let [column, color] of Object.entries(this.color)) {
124
+ if (type_ === 'agepyramid') {
125
+ //set category color
126
+ ctx.fillStyle = color
127
+
128
+ //get category value
129
+ const val = cell[column]
130
+
131
+ //compute category length - in geo
132
+ /** @type {number} */
133
+ const wG = (sG * val) / maxVal
134
+
135
+ //draw bar
136
+ ctx.fillRect(xc + (resolution - wG) / 2, yc + cumul, wG, incr)
137
+
138
+ //next height
139
+ cumul += incr
140
+ } else if (type_ === 'radar') {
141
+ //set category color
142
+ ctx.fillStyle = color
143
+
144
+ //get categroy value
145
+ const val = cell[column]
146
+
147
+ //compute category radius - in geo
148
+ /** @type {number} */
149
+ //const rG = this.radius(val, r, stat, cellStat, z)
150
+ const rG = (sG / 2) * Math.sqrt(val / maxVal)
151
+
152
+ //draw angular sector
153
+ ctx.beginPath()
154
+ ctx.moveTo(xc, yc)
155
+ ctx.arc(xc, yc, rG, cumul - incr, cumul)
156
+ ctx.lineTo(xc, yc)
157
+ ctx.fill()
158
+
159
+ //next angular sector
160
+ cumul += incr
161
+ } else if (type_ === 'halftone') {
162
+ //set category color
163
+ ctx.fillStyle = color
164
+
165
+ //get categroy value
166
+ const val = cell[column]
167
+
168
+ //compute category radius - in geo
169
+ /** @type {number} */
170
+ const rG = sG * 0.333 * Math.sqrt(val / maxVal)
171
+
172
+ //draw circle
173
+ ctx.beginPath()
174
+ ctx.arc(
175
+ xc + resolution * 0.25 * Math.cos(cumul),
176
+ yc + resolution * 0.25 * Math.sin(cumul),
177
+ rG,
178
+ 0,
179
+ 2 * Math.PI
180
+ )
181
+ ctx.fill()
182
+
183
+ //next angular sector
184
+ cumul += incr
185
+ } else {
186
+ throw new Error('Unexpected symbol type:' + type_)
187
+ }
188
+ }
189
+ } else {
190
+ //compute total
191
+ let total = 0
192
+ for (let column of Object.keys(this.color)) {
193
+ const v = +cell[column]
194
+ if (!v) continue
195
+ total += v
196
+ }
197
+ if (!total || isNaN(total)) continue
198
+
199
+ //draw decomposition symbol
200
+ let cumul = 0
201
+ const d = resolution * (1 - sG / resolution) * 0.5
202
+ const ori = this.stripesOrientation(cell, resolution, z, viewScale)
203
+
204
+ for (let [column, color] of Object.entries(this.color)) {
205
+ //get share
206
+ const share = cell[column] / total
207
+ if (!share || isNaN(share)) continue
208
+
209
+ //set color
210
+ ctx.fillStyle = color
211
+
212
+ //draw symbol part
213
+ if (type_ === 'flag') {
214
+ //draw flag stripe
215
+ if (ori == 0) {
216
+ //horizontal
217
+ ctx.fillRect(
218
+ cell.x + d + offset.dx,
219
+ cell.y + d + cumul * sG + offset.dy,
220
+ sG,
221
+ share * sG
222
+ )
223
+ } else {
224
+ //vertical
225
+ ctx.fillRect(
226
+ cell.x + d + cumul * sG + offset.dx,
227
+ cell.y + d + offset.dy,
228
+ share * sG,
229
+ sG
230
+ )
231
+ }
232
+ } else if (type_ === 'piechart') {
233
+ //draw pie chart angular sector
234
+
235
+ //compute angles
236
+ const a1 = cumul * 2 * Math.PI
237
+ const a2 = (cumul + share) * 2 * Math.PI
238
+
239
+ //draw
240
+ ctx.beginPath()
241
+ ctx.moveTo(xc, yc)
242
+ ctx.arc(xc, yc, sG * 0.5, a1 + offAng, a2 + offAng)
243
+ if (this.pieChartInternalRadiusFactor)
244
+ ctx.arc(
245
+ xc,
246
+ yc,
247
+ sG * 0.5 * this.pieChartInternalRadiusFactor,
248
+ a1 + offAng,
249
+ a2 + offAng,
250
+ true
251
+ )
252
+ ctx.closePath()
253
+ ctx.fill()
254
+ } else if (type_ === 'ring') {
255
+ //draw ring
256
+ ctx.beginPath()
257
+ ctx.arc(xc, yc, Math.sqrt(1 - cumul) * sG * 0.5, 0, 2 * Math.PI)
258
+ ctx.fill()
259
+ } else if (type_ === 'segment') {
260
+ //draw segment sections
261
+ const wG = (sG * sG) / resolution
262
+ if (ori == 0) {
263
+ //horizontal
264
+ ctx.fillRect(
265
+ cell.x + offset.dx,
266
+ cell.y + (resolution - wG) / 2 + cumul * wG + offset.dy,
267
+ resolution,
268
+ share * wG
269
+ )
270
+ } else {
271
+ //vertical
272
+ ctx.fillRect(
273
+ cell.x + cumul * resolution + offset.dx,
274
+ cell.y + (resolution - wG) / 2 + offset.dy,
275
+ share * resolution,
276
+ wG
277
+ )
278
+ }
279
+ } else {
280
+ throw new Error('Unexpected symbol type:' + type_)
281
+ }
282
+
283
+ cumul += share
284
+ }
285
+ }
286
+ }
287
+
288
+ //update legends
289
+ this.updateLegends({ style: this, resolution: resolution, z: z, viewScale: viewScale })
290
+ }
291
+ }