gridviz 2.0.38 → 2.0.40

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 +7945 -8887
  3. package/dist/gridviz.min.js +1 -1
  4. package/package.json +77 -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 +174 -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/LegoStyle.js +112 -112
  35. package/src/style/MosaicStyle.js +107 -107
  36. package/src/style/NinjaStarStyle.js +124 -124
  37. package/src/style/PillarStyle.js +230 -230
  38. package/src/style/SegmentStyle.js +142 -142
  39. package/src/style/ShapeColorSizeStyle.js +126 -126
  40. package/src/style/SideCatStyle.js +172 -172
  41. package/src/style/SideStyle.js +218 -218
  42. package/src/style/SquareColorCatWGLStyle.js +120 -120
  43. package/src/style/SquareColorWGLStyle.js +146 -146
  44. package/src/style/StrokeStyle.js +131 -131
  45. package/src/style/TanakaStyle.js +160 -160
  46. package/src/style/TextStyle.js +132 -132
  47. package/src/utils/Utils.js +35 -35
  48. package/src/utils/WebGLRectangleColoring.js +106 -106
  49. package/src/utils/WebGLSquareColoring.js +118 -118
  50. package/src/utils/WebGLSquareColoringAdvanced.js +230 -230
  51. package/src/utils/WebGLSquareColoringCatAdvanced.js +133 -133
  52. package/src/utils/WebGLSquareColoringKS.js +153 -153
  53. package/src/utils/stretching.js +131 -131
  54. package/src/utils/webGLUtils.js +71 -71
  55. package/src/utils/zoomUtils.js +142 -142
  56. package/src/style/KernelSmoothingOldStyle.js +0 -221
  57. package/src/style/KernelSmoothingStyle.js +0 -115
  58. package/src/style/KernelSmoothingWGLStyle.js +0 -130
@@ -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
+ }