gridviz 2.0.38 → 2.0.39

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 (58) hide show
  1. package/README.md +119 -119
  2. package/dist/gridviz.js +7488 -7530
  3. package/dist/gridviz.min.js +1 -1
  4. package/package.json +78 -78
  5. package/src/App.js +698 -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 +103 -103
  10. package/src/GeoCanvas.js +419 -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/ParquetGrid.js +122 -122
  22. package/src/dataset/TiledGrid.js +296 -296
  23. package/src/index.js +177 -177
  24. package/src/legend/ColorCategoryLegend.js +124 -124
  25. package/src/legend/ColorDiscreteLegend.js +105 -105
  26. package/src/legend/ColorLegend.js +125 -125
  27. package/src/legend/SegmentOrientationLegend.js +87 -87
  28. package/src/legend/SegmentWidthLegend.js +97 -97
  29. package/src/legend/SizeLegend.js +141 -141
  30. package/src/style/CompositionStyle.js +300 -300
  31. package/src/style/ContourStyle.js +54 -54
  32. package/src/style/DotDensityStyle.js +156 -156
  33. package/src/style/JoyPlotStyle.js +135 -135
  34. package/src/style/KernelSmoothingOldStyle.js +221 -221
  35. package/src/style/KernelSmoothingStyle.js +115 -115
  36. package/src/style/KernelSmoothingWGLStyle.js +130 -130
  37. package/src/style/LegoStyle.js +112 -112
  38. package/src/style/MosaicStyle.js +107 -107
  39. package/src/style/NinjaStarStyle.js +124 -124
  40. package/src/style/PillarStyle.js +230 -230
  41. package/src/style/SegmentStyle.js +142 -142
  42. package/src/style/ShapeColorSizeStyle.js +126 -126
  43. package/src/style/SideCatStyle.js +172 -172
  44. package/src/style/SideStyle.js +218 -218
  45. package/src/style/SquareColorCatWGLStyle.js +120 -120
  46. package/src/style/SquareColorWGLStyle.js +146 -146
  47. package/src/style/StrokeStyle.js +131 -131
  48. package/src/style/TanakaStyle.js +160 -160
  49. package/src/style/TextStyle.js +132 -132
  50. package/src/utils/Utils.js +35 -35
  51. package/src/utils/WebGLRectangleColoring.js +106 -106
  52. package/src/utils/WebGLSquareColoring.js +118 -118
  53. package/src/utils/WebGLSquareColoringAdvanced.js +230 -230
  54. package/src/utils/WebGLSquareColoringCatAdvanced.js +133 -133
  55. package/src/utils/WebGLSquareColoringKS.js +153 -153
  56. package/src/utils/stretching.js +131 -131
  57. package/src/utils/webGLUtils.js +71 -71
  58. package/src/utils/zoomUtils.js +142 -142
@@ -1,131 +1,131 @@
1
- //@ts-check
2
- 'use strict'
3
-
4
- import { Style } from '../Style.js'
5
-
6
- /**
7
- *
8
- * @author Julien Gaffuri
9
- */
10
- export class StrokeStyle extends Style {
11
- /** @param {object} opts */
12
- constructor(opts) {
13
- super(opts)
14
- opts = opts || {}
15
-
16
- /** The name of the column/attribute of the tabular data where to retrieve the variable for color.
17
- * @type {string} */
18
- this.strokeColorCol = opts.strokeColorCol
19
-
20
- /** A function returning the color of the stroke.
21
- * @type {function(number,number,import("../Style").Stat|undefined):string} */
22
- this.strokeColor = opts.strokeColor || (() => '#666')
23
-
24
- /** The name of the column/attribute of the tabular data where to retrieve the variable for size.
25
- * @type {string} */
26
- this.sizeCol = opts.sizeCol
27
-
28
- /** A function returning the size of a cell in geographical unit.
29
- * @type {function(number,number,import("../Style").Stat|undefined,number):number} */
30
- this.size = opts.size
31
-
32
- /** The stroke line width, in pixels.
33
- * @type {string} */
34
- this.strokeWidthCol = opts.strokeWidthCol
35
-
36
- /** The stroke line width in geographical unit.
37
- * @type {function(number,number,import("../Style").Stat|undefined,number):number} */
38
- this.strokeWidth = opts.strokeWidth // (v,r,s,z)=>...
39
-
40
- /** A function returning the shape of a cell.
41
- * @type {function(import("../Dataset").Cell):import("../Style").Shape} */
42
- this.shape = opts.shape || (() => 'square')
43
- }
44
-
45
- /**
46
- * Draw cells as squares, with various colors and size.
47
- *
48
- * @param {Array.<import("../Dataset").Cell>} cells
49
- * @param {number} r
50
- * @param {import("../GeoCanvas").GeoCanvas} cg
51
- */
52
- draw(cells, r, cg) {
53
- //filter
54
- if (this.filter) cells = cells.filter(this.filter)
55
-
56
- //zoom factor
57
- const zf = cg.getZf()
58
-
59
- let statColor
60
- if (this.strokeColorCol) statColor = Style.getStatistics(cells, (c) => c[this.strokeColorCol], true)
61
-
62
- let statSize
63
- if (this.sizeCol) statSize = Style.getStatistics(cells, (c) => c[this.sizeCol], true)
64
-
65
- let statWidth
66
- if (this.strokeWidthCol) statWidth = Style.getStatistics(cells, (c) => c[this.strokeWidthCol], true)
67
-
68
- //draw with HTML canvas
69
- //in geo coordinates
70
- cg.setCanvasTransform()
71
-
72
- const r2 = r * 0.5
73
- for (let cell of cells) {
74
- //color
75
- const col = this.strokeColor
76
- ? this.strokeColor(cell[this.strokeColorCol], r, statColor)
77
- : undefined
78
- if (!col || col === 'none') continue
79
- cg.ctx.strokeStyle = col
80
-
81
- //size
82
- /** @type {function(number,number,import("../Style").Stat|undefined,number):number} */
83
- let s_ = this.size || (() => r)
84
- //size - in geo unit
85
- const sG = s_(cell[this.sizeCol], r, statSize, zf)
86
-
87
- //width
88
- const wi = this.strokeWidth
89
- ? this.strokeWidth(cell[this.strokeWidthCol], r, statWidth, zf)
90
- : 1 * zf
91
- if (!wi || wi <= 0) continue
92
- cg.ctx.lineWidth = wi
93
-
94
- //shape
95
- const shape = this.shape ? this.shape(cell) : 'square'
96
- if (shape === 'none') continue
97
-
98
- //get offset
99
- const offset = this.offset(cell, r, zf)
100
-
101
- if (shape === 'square') {
102
- //draw square
103
- const d = r * (1 - sG / r) * 0.5
104
- cg.ctx.beginPath()
105
- cg.ctx.rect(cell.x + d + offset.dx, cell.y + d + offset.dy, sG, sG)
106
- cg.ctx.stroke()
107
- } else if (shape === 'circle') {
108
- //draw circle
109
- cg.ctx.beginPath()
110
- cg.ctx.arc(cell.x + r2 + offset.dx, cell.y + r2 + offset.dy, sG * 0.5, 0, 2 * Math.PI, false)
111
- cg.ctx.stroke()
112
- } else if (shape === 'diamond') {
113
- const s2 = sG * 0.5
114
- cg.ctx.beginPath()
115
- cg.ctx.moveTo(cell.x + r2 - s2, cell.y + r2)
116
- cg.ctx.lineTo(cell.x + r2, cell.y + r2 + s2)
117
- cg.ctx.lineTo(cell.x + r2 + s2, cell.y + r2)
118
- cg.ctx.lineTo(cell.x + r2, cell.y + r2 - s2)
119
- cg.ctx.lineTo(cell.x + r2 - s2, cell.y + r2)
120
- cg.ctx.stroke()
121
- } else if (shape === 'donut') {
122
- console.error('Not implemented')
123
- } else {
124
- throw new Error('Unexpected shape:' + shape)
125
- }
126
- }
127
-
128
- //update legends
129
- //this.updateLegends({ style: this, r: resolution, zf: zf, sSize: statSize, sColor: statColor });
130
- }
131
- }
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ import { Style } from '../Style.js'
5
+
6
+ /**
7
+ *
8
+ * @author Julien Gaffuri
9
+ */
10
+ export class StrokeStyle extends Style {
11
+ /** @param {object} opts */
12
+ constructor(opts) {
13
+ super(opts)
14
+ opts = opts || {}
15
+
16
+ /** The name of the column/attribute of the tabular data where to retrieve the variable for color.
17
+ * @type {string} */
18
+ this.strokeColorCol = opts.strokeColorCol
19
+
20
+ /** A function returning the color of the stroke.
21
+ * @type {function(number,number,import("../Style").Stat|undefined):string} */
22
+ this.strokeColor = opts.strokeColor || (() => '#666')
23
+
24
+ /** The name of the column/attribute of the tabular data where to retrieve the variable for size.
25
+ * @type {string} */
26
+ this.sizeCol = opts.sizeCol
27
+
28
+ /** A function returning the size of a cell in geographical unit.
29
+ * @type {function(number,number,import("../Style").Stat|undefined,number):number} */
30
+ this.size = opts.size
31
+
32
+ /** The stroke line width, in pixels.
33
+ * @type {string} */
34
+ this.strokeWidthCol = opts.strokeWidthCol
35
+
36
+ /** The stroke line width in geographical unit.
37
+ * @type {function(number,number,import("../Style").Stat|undefined,number):number} */
38
+ this.strokeWidth = opts.strokeWidth // (v,r,s,z)=>...
39
+
40
+ /** A function returning the shape of a cell.
41
+ * @type {function(import("../Dataset").Cell):import("../Style").Shape} */
42
+ this.shape = opts.shape || (() => 'square')
43
+ }
44
+
45
+ /**
46
+ * Draw cells as squares, with various colors and size.
47
+ *
48
+ * @param {Array.<import("../Dataset").Cell>} cells
49
+ * @param {number} r
50
+ * @param {import("../GeoCanvas").GeoCanvas} cg
51
+ */
52
+ draw(cells, r, cg) {
53
+ //filter
54
+ if (this.filter) cells = cells.filter(this.filter)
55
+
56
+ //zoom factor
57
+ const zf = cg.getZf()
58
+
59
+ let statColor
60
+ if (this.strokeColorCol) statColor = Style.getStatistics(cells, (c) => c[this.strokeColorCol], true)
61
+
62
+ let statSize
63
+ if (this.sizeCol) statSize = Style.getStatistics(cells, (c) => c[this.sizeCol], true)
64
+
65
+ let statWidth
66
+ if (this.strokeWidthCol) statWidth = Style.getStatistics(cells, (c) => c[this.strokeWidthCol], true)
67
+
68
+ //draw with HTML canvas
69
+ //in geo coordinates
70
+ cg.setCanvasTransform()
71
+
72
+ const r2 = r * 0.5
73
+ for (let cell of cells) {
74
+ //color
75
+ const col = this.strokeColor
76
+ ? this.strokeColor(cell[this.strokeColorCol], r, statColor)
77
+ : undefined
78
+ if (!col || col === 'none') continue
79
+ cg.ctx.strokeStyle = col
80
+
81
+ //size
82
+ /** @type {function(number,number,import("../Style").Stat|undefined,number):number} */
83
+ let s_ = this.size || (() => r)
84
+ //size - in geo unit
85
+ const sG = s_(cell[this.sizeCol], r, statSize, zf)
86
+
87
+ //width
88
+ const wi = this.strokeWidth
89
+ ? this.strokeWidth(cell[this.strokeWidthCol], r, statWidth, zf)
90
+ : 1 * zf
91
+ if (!wi || wi <= 0) continue
92
+ cg.ctx.lineWidth = wi
93
+
94
+ //shape
95
+ const shape = this.shape ? this.shape(cell) : 'square'
96
+ if (shape === 'none') continue
97
+
98
+ //get offset
99
+ const offset = this.offset(cell, r, zf)
100
+
101
+ if (shape === 'square') {
102
+ //draw square
103
+ const d = r * (1 - sG / r) * 0.5
104
+ cg.ctx.beginPath()
105
+ cg.ctx.rect(cell.x + d + offset.dx, cell.y + d + offset.dy, sG, sG)
106
+ cg.ctx.stroke()
107
+ } else if (shape === 'circle') {
108
+ //draw circle
109
+ cg.ctx.beginPath()
110
+ cg.ctx.arc(cell.x + r2 + offset.dx, cell.y + r2 + offset.dy, sG * 0.5, 0, 2 * Math.PI, false)
111
+ cg.ctx.stroke()
112
+ } else if (shape === 'diamond') {
113
+ const s2 = sG * 0.5
114
+ cg.ctx.beginPath()
115
+ cg.ctx.moveTo(cell.x + r2 - s2, cell.y + r2)
116
+ cg.ctx.lineTo(cell.x + r2, cell.y + r2 + s2)
117
+ cg.ctx.lineTo(cell.x + r2 + s2, cell.y + r2)
118
+ cg.ctx.lineTo(cell.x + r2, cell.y + r2 - s2)
119
+ cg.ctx.lineTo(cell.x + r2 - s2, cell.y + r2)
120
+ cg.ctx.stroke()
121
+ } else if (shape === 'donut') {
122
+ console.error('Not implemented')
123
+ } else {
124
+ throw new Error('Unexpected shape:' + shape)
125
+ }
126
+ }
127
+
128
+ //update legends
129
+ //this.updateLegends({ style: this, r: resolution, zf: zf, sSize: statSize, sColor: statColor });
130
+ }
131
+ }
@@ -1,160 +1,160 @@
1
- //@ts-check
2
- 'use strict'
3
-
4
- import { SquareColorWGLStyle } from './SquareColorWGLStyle.js'
5
- import { SideStyle } from './SideStyle.js'
6
-
7
- /**
8
- *
9
- * @see https://manifold.net/doc/mfd9/example__tanaka_contours.htm
10
- *
11
- * @author Julien Gaffuri
12
- */
13
- export class TanakaStyle {
14
- /**
15
- * @param {string} col
16
- * @param {object} opts
17
- * @returns {Array.<import("../Style").Style>}
18
- */
19
- static get(col, opts) {
20
- opts = opts || {}
21
-
22
- //get colors from d3 ramps, if 'nb' is specified
23
- if (opts.nb != undefined) {
24
- if (opts.nb < 2) {
25
- console.error('unexpected number of colors in tanaka (<2): ' + opts.nb)
26
- opts.nb = 2
27
- }
28
- if (!opts.color) {
29
- console.error('color function not defined in tanaka')
30
- opts.color = () => 'gray'
31
- }
32
- opts.colors = []
33
- for (let i = 0; i < opts.nb; i++) opts.colors.push(opts.color(i / (opts.nb - 1)))
34
- }
35
-
36
- /**
37
- * The colors.
38
- * @type {Array.<string>} */
39
- opts.colors = opts.colors || ['#a9bb9e', '#c9dcaa', '#fde89f', '#f9a579', '#eb444b']
40
- const nb = opts.colors.length
41
-
42
- /** A function to compute 't' from the value v
43
- * @type {function(number,number,import("../Style").Stat):number} */
44
- opts.tFun = opts.tFun || ((v, r, s) => (v - s.min) / (s.max - s.min))
45
-
46
- //shadow colors
47
- opts.colDark = opts.colDark || '#111'
48
- opts.colBright = opts.colBright || '#ddd'
49
-
50
- //width of the segment (share of the resolution)
51
- opts.widthFactor = opts.widthFactor || 0.08
52
-
53
- //shading
54
- opts.newShading = opts.newShading
55
- opts.newShadingWidthPix = opts.newShadingWidthPix || 2
56
- //transparency value, within [0,1]
57
- opts.newShadingTr =
58
- opts.newShadingTr ||
59
- ((sideValue, sideStat) =>
60
- Math.abs(sideValue) / Math.max(Math.abs(sideStat.min), Math.abs(sideStat.max)))
61
-
62
- /**
63
- * @param {number} t A cell t value, within [0,1].
64
- * @returns the class number for the value
65
- */
66
- const getClass = (t) => {
67
- if (isNaN(t) || t == undefined) {
68
- console.error('Unexpected t value 1: ' + t)
69
- return -9
70
- }
71
- for (let i = 0; i < nb; i++) if (t <= (i + 1) / nb) return i
72
- console.error('Unexpected t value 2: ' + t)
73
- return -9
74
- }
75
-
76
- const colStyle = new SquareColorWGLStyle({
77
- colorCol: col,
78
- colors: opts.colors,
79
- tFun: (v, r, s) => {
80
- const t = opts.tFun(v, r, s)
81
- const c = getClass(t)
82
- return c / (nb - 1)
83
- },
84
- //stretching: { fun: "expRev", alpha: -7 },
85
- size: (r, zf) => r + 0.5 * zf, //that is to ensure no gap between same class cells is visible
86
- filter: opts.filter,
87
- })
88
-
89
- /*
90
- if no web gl:
91
- const colStyle = new ShapeColorSizeStyle({
92
- colorCol: col,
93
- //the color corresponding to the class
94
- color: (v, r, s, zf) => {
95
- if (v == 0 && opts.tFun && isNaN(opts.tFun(v, r, s)))
96
- return undefined
97
- return opts.colors[getClass(opts.tFun ? opts.tFun(v, r, s) : v)]
98
- },
99
- shape: () => "square",
100
- size: (v, r, s, zf) => r + 0.5 * zf, //that is to ensure no gap between same class cells is visible
101
- })
102
- */
103
-
104
- /** The side style, for the shadow effect */
105
- const sideStyle = new SideStyle({
106
- valueCol: col,
107
- value: (v1, v2, r, s, zf) => {
108
- //compute the number of classes of difference
109
- if (v1 === undefined && v2 === undefined) return 0
110
- else if (v2 === undefined) {
111
- const t = opts.tFun(v1, r, s)
112
- if (t == undefined || isNaN(t)) throw new Error('Unexpected value: ' + v1 + ' - ' + t)
113
- const c = getClass(t)
114
- return c + 1
115
- } else if (v1 === undefined) {
116
- const t = opts.tFun(v2, r, s)
117
- if (t == undefined || isNaN(t)) throw new Error('Unexpected value: ' + v2 + ' - ' + t)
118
- const c = getClass(t)
119
- return -c - 1
120
- }
121
- const t1 = opts.tFun(v1, r, s)
122
- if (t1 == undefined || isNaN(t1)) throw new Error('Unexpected value: ' + v1 + ' - ' + t1)
123
- const t2 = opts.tFun(v2, r, s)
124
- if (t2 == undefined || isNaN(t2)) throw new Error('Unexpected value: ' + v2 + ' - ' + t2)
125
- const c1 = getClass(t1)
126
- const c2 = getClass(t2)
127
- return -c2 + c1
128
- },
129
-
130
- color: opts.newShading
131
- ? //black with transparency depending on difference
132
- (side, r, s, z) => {
133
- const tr = opts.newShadingTr(side.value, s)
134
- return (side.value > 0 && side.or === 'h') || (side.value < 0 && side.or === 'v')
135
- ? 'rgba(255,255,100,' + tr + ')'
136
- : 'rgba(0,0,0,' + tr + ')'
137
- }
138
- : //white or black, depending on orientation and value
139
- (side, r, s, z) => {
140
- if (side.value === 0) return
141
- //return "gray"
142
- if (side.or === 'v') return side.value < 0 ? opts.colBright : opts.colDark
143
- return side.value < 0 ? opts.colDark : opts.colBright
144
- },
145
-
146
- width: opts.newShading
147
- ? //fill size
148
- (side, r, s, z) => {
149
- return opts.newShadingWidthPix * z
150
- }
151
- : //width depends on the value, that is the number of classes of difference
152
- (side, r, s, z) =>
153
- opts.widthFactor * r * Math.abs(side.value) * (side.or === 'v' ? 0.5 : 1),
154
-
155
- filter: opts.filter,
156
- })
157
-
158
- return [colStyle, sideStyle]
159
- }
160
- }
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ import { SquareColorWGLStyle } from './SquareColorWGLStyle.js'
5
+ import { SideStyle } from './SideStyle.js'
6
+
7
+ /**
8
+ *
9
+ * @see https://manifold.net/doc/mfd9/example__tanaka_contours.htm
10
+ *
11
+ * @author Julien Gaffuri
12
+ */
13
+ export class TanakaStyle {
14
+ /**
15
+ * @param {string} col
16
+ * @param {object} opts
17
+ * @returns {Array.<import("../Style").Style>}
18
+ */
19
+ static get(col, opts) {
20
+ opts = opts || {}
21
+
22
+ //get colors from d3 ramps, if 'nb' is specified
23
+ if (opts.nb != undefined) {
24
+ if (opts.nb < 2) {
25
+ console.error('unexpected number of colors in tanaka (<2): ' + opts.nb)
26
+ opts.nb = 2
27
+ }
28
+ if (!opts.color) {
29
+ console.error('color function not defined in tanaka')
30
+ opts.color = () => 'gray'
31
+ }
32
+ opts.colors = []
33
+ for (let i = 0; i < opts.nb; i++) opts.colors.push(opts.color(i / (opts.nb - 1)))
34
+ }
35
+
36
+ /**
37
+ * The colors.
38
+ * @type {Array.<string>} */
39
+ opts.colors = opts.colors || ['#a9bb9e', '#c9dcaa', '#fde89f', '#f9a579', '#eb444b']
40
+ const nb = opts.colors.length
41
+
42
+ /** A function to compute 't' from the value v
43
+ * @type {function(number,number,import("../Style").Stat):number} */
44
+ opts.tFun = opts.tFun || ((v, r, s) => (v - s.min) / (s.max - s.min))
45
+
46
+ //shadow colors
47
+ opts.colDark = opts.colDark || '#111'
48
+ opts.colBright = opts.colBright || '#ddd'
49
+
50
+ //width of the segment (share of the resolution)
51
+ opts.widthFactor = opts.widthFactor || 0.08
52
+
53
+ //shading
54
+ opts.newShading = opts.newShading
55
+ opts.newShadingWidthPix = opts.newShadingWidthPix || 2
56
+ //transparency value, within [0,1]
57
+ opts.newShadingTr =
58
+ opts.newShadingTr ||
59
+ ((sideValue, sideStat) =>
60
+ Math.abs(sideValue) / Math.max(Math.abs(sideStat.min), Math.abs(sideStat.max)))
61
+
62
+ /**
63
+ * @param {number} t A cell t value, within [0,1].
64
+ * @returns the class number for the value
65
+ */
66
+ const getClass = (t) => {
67
+ if (isNaN(t) || t == undefined) {
68
+ console.error('Unexpected t value 1: ' + t)
69
+ return -9
70
+ }
71
+ for (let i = 0; i < nb; i++) if (t <= (i + 1) / nb) return i
72
+ console.error('Unexpected t value 2: ' + t)
73
+ return -9
74
+ }
75
+
76
+ const colStyle = new SquareColorWGLStyle({
77
+ colorCol: col,
78
+ colors: opts.colors,
79
+ tFun: (v, r, s) => {
80
+ const t = opts.tFun(v, r, s)
81
+ const c = getClass(t)
82
+ return c / (nb - 1)
83
+ },
84
+ //stretching: { fun: "expRev", alpha: -7 },
85
+ size: (r, zf) => r + 0.5 * zf, //that is to ensure no gap between same class cells is visible
86
+ filter: opts.filter,
87
+ })
88
+
89
+ /*
90
+ if no web gl:
91
+ const colStyle = new ShapeColorSizeStyle({
92
+ colorCol: col,
93
+ //the color corresponding to the class
94
+ color: (v, r, s, zf) => {
95
+ if (v == 0 && opts.tFun && isNaN(opts.tFun(v, r, s)))
96
+ return undefined
97
+ return opts.colors[getClass(opts.tFun ? opts.tFun(v, r, s) : v)]
98
+ },
99
+ shape: () => "square",
100
+ size: (v, r, s, zf) => r + 0.5 * zf, //that is to ensure no gap between same class cells is visible
101
+ })
102
+ */
103
+
104
+ /** The side style, for the shadow effect */
105
+ const sideStyle = new SideStyle({
106
+ valueCol: col,
107
+ value: (v1, v2, r, s, zf) => {
108
+ //compute the number of classes of difference
109
+ if (v1 === undefined && v2 === undefined) return 0
110
+ else if (v2 === undefined) {
111
+ const t = opts.tFun(v1, r, s)
112
+ if (t == undefined || isNaN(t)) throw new Error('Unexpected value: ' + v1 + ' - ' + t)
113
+ const c = getClass(t)
114
+ return c + 1
115
+ } else if (v1 === undefined) {
116
+ const t = opts.tFun(v2, r, s)
117
+ if (t == undefined || isNaN(t)) throw new Error('Unexpected value: ' + v2 + ' - ' + t)
118
+ const c = getClass(t)
119
+ return -c - 1
120
+ }
121
+ const t1 = opts.tFun(v1, r, s)
122
+ if (t1 == undefined || isNaN(t1)) throw new Error('Unexpected value: ' + v1 + ' - ' + t1)
123
+ const t2 = opts.tFun(v2, r, s)
124
+ if (t2 == undefined || isNaN(t2)) throw new Error('Unexpected value: ' + v2 + ' - ' + t2)
125
+ const c1 = getClass(t1)
126
+ const c2 = getClass(t2)
127
+ return -c2 + c1
128
+ },
129
+
130
+ color: opts.newShading
131
+ ? //black with transparency depending on difference
132
+ (side, r, s, z) => {
133
+ const tr = opts.newShadingTr(side.value, s)
134
+ return (side.value > 0 && side.or === 'h') || (side.value < 0 && side.or === 'v')
135
+ ? 'rgba(255,255,100,' + tr + ')'
136
+ : 'rgba(0,0,0,' + tr + ')'
137
+ }
138
+ : //white or black, depending on orientation and value
139
+ (side, r, s, z) => {
140
+ if (side.value === 0) return
141
+ //return "gray"
142
+ if (side.or === 'v') return side.value < 0 ? opts.colBright : opts.colDark
143
+ return side.value < 0 ? opts.colDark : opts.colBright
144
+ },
145
+
146
+ width: opts.newShading
147
+ ? //fill size
148
+ (side, r, s, z) => {
149
+ return opts.newShadingWidthPix * z
150
+ }
151
+ : //width depends on the value, that is the number of classes of difference
152
+ (side, r, s, z) =>
153
+ opts.widthFactor * r * Math.abs(side.value) * (side.or === 'v' ? 0.5 : 1),
154
+
155
+ filter: opts.filter,
156
+ })
157
+
158
+ return [colStyle, sideStyle]
159
+ }
160
+ }