gridviz 3.0.14 → 3.0.16

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 +127 -128
  2. package/dist/gridviz.js +7959 -7860
  3. package/dist/gridviz.min.js +1 -1
  4. package/package.json +74 -74
  5. package/src/button/ZoomButtons.js +101 -96
  6. package/src/core/Dataset.js +154 -157
  7. package/src/core/Drawable.js +60 -61
  8. package/src/core/GeoCanvas.js +409 -370
  9. package/src/core/Layer.js +23 -25
  10. package/src/core/Legend.js +108 -110
  11. package/src/core/Map.js +495 -495
  12. package/src/core/MultiResolutionDataset.js +93 -97
  13. package/src/core/Style.js +98 -99
  14. package/src/dataset/CSVGrid.js +112 -112
  15. package/src/dataset/GeoTIFF.js +122 -123
  16. package/src/dataset/JSGrid.js +55 -54
  17. package/src/dataset/TiledGrid.js +289 -288
  18. package/src/dataset/worker.js +18 -0
  19. package/src/index.js +77 -71
  20. package/src/layer/BackgroundLayer.js +162 -158
  21. package/src/layer/BackgroundLayerImage.js +81 -84
  22. package/src/layer/BackgroundLayerWMS.js +104 -108
  23. package/src/layer/GeoJSONLayer.js +214 -220
  24. package/src/layer/GridLayer.js +148 -157
  25. package/src/layer/LabelLayer.js +194 -193
  26. package/src/legend/ColorCategoryLegend.js +109 -110
  27. package/src/legend/ColorDiscreteLegend.js +100 -102
  28. package/src/legend/ColorLegend.js +115 -118
  29. package/src/legend/OrientationLegend.js +89 -91
  30. package/src/legend/SizeLegend.js +224 -224
  31. package/src/legend/TernaryLegend.js +302 -210
  32. package/src/style/CompositionStyle.js +291 -288
  33. package/src/style/DotDensityStyle.js +133 -134
  34. package/src/style/ImageStyle.js +100 -102
  35. package/src/style/IsoFenceStyle.js +217 -203
  36. package/src/style/JoyPlotStyle.js +127 -128
  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 -208
  41. package/src/style/SegmentStyle.js +105 -105
  42. package/src/style/ShapeColorSizeStyle.js +147 -132
  43. package/src/style/SideCategoryStyle.js +112 -114
  44. package/src/style/SideStyle.js +212 -205
  45. package/src/style/SquareColorCategoryWebGLStyle.js +107 -108
  46. package/src/style/SquareColorWebGLStyle.js +126 -126
  47. package/src/style/StrokeStyle.js +135 -136
  48. package/src/style/TanakaStyle.js +69 -68
  49. package/src/style/TextStyle.js +110 -111
  50. package/src/style/TimeSeriesStyle.js +222 -229
  51. package/src/utils/scale.js +218 -228
  52. package/src/utils/stretching.js +120 -133
  53. package/src/utils/ternary.js +203 -203
  54. package/src/utils/utils.js +58 -63
  55. package/src/utils/webGLUtils.js +72 -70
@@ -1,224 +1,224 @@
1
- //@ts-check
2
- 'use strict'
3
-
4
- import { Legend } from '../core/Legend.js'
5
- import { nice } from '../utils/utils.js'
6
- import { max } from 'd3-array'
7
-
8
- /**
9
- * A legend element for proportional symbols.
10
- *
11
- * @module legend
12
- * @author Joseph Davies, Julien Gaffuri
13
- */
14
- export class SizeLegend extends Legend {
15
- /** @param {Object} opts */
16
- constructor(opts) {
17
- super(opts)
18
- opts = opts || {}
19
-
20
- /** A function returning the text label, from the view scale and list of cells, resolution and zoom
21
- * @type { function(object, Array.<import('../core/Dataset.js').Cell>, number, number):(number|string) } */
22
- this.label = opts.label || undefined
23
-
24
- /** A function returning the size of the legend symbol, in geo UoM, from the viewscale, resolution and zoom
25
- * @type { function(object, number, number):number } */
26
- this.size = opts.size || undefined
27
-
28
- //symbol
29
- /** @type {(import("../core/Style").Shape)|"line"} */
30
- this.shape = opts.shape || 'circle'
31
-
32
- //general case
33
- this.fillColor = opts.fillColor || 'none'
34
- this.strokeColor = opts.strokeColor || 'gray'
35
- this.strokeWidth = opts.strokeWidth || 1
36
-
37
- //for line shape
38
- //TODO this.orientation = opts.orientation || 0
39
- this.color = opts.color || 'gray'
40
- this.length = opts.length || ((resolution, z, viewScale) => resolution)
41
- }
42
-
43
- /**
44
- * @param {{ viewScale:object, resolution: number, z:number, cells:Array.<import('../core/Dataset.js').Cell> }} opts
45
- */
46
- update(opts) {
47
-
48
- //clear
49
- this.div.selectAll('*').remove()
50
-
51
- //title
52
- this.makeTitle()
53
-
54
- //get label. May not be a number (!)
55
- let label = this.label(opts.viewScale, opts.cells, opts.resolution, opts.z)
56
-
57
- //compute size of symbol, in pix
58
- let sizePix
59
- if (this.size)
60
- sizePix = this.size(opts.viewScale, opts.resolution, opts.z) / opts.z
61
- else
62
- sizePix = opts.viewScale(+label) / opts.z
63
- if (!sizePix) return
64
-
65
- //format label, if specified and possible
66
- if (this.labelFormat && !isNaN(+label)) label = this.labelFormat(label)
67
-
68
- const d = this.div.append('div')
69
- //to enable vertical centering
70
- //.style("position", "relative")
71
-
72
- //default svg construction, for square and circle
73
- const svg = () => d
74
- .append('svg')
75
- .attr('width', sizePix + this.strokeWidth + 2)
76
- .attr('height', sizePix + this.strokeWidth + 2)
77
- .style('', 'inline-block')
78
-
79
- if (this.shape === 'square') {
80
- svg().append('rect')
81
- .attr('x', 0)
82
- .attr('y', 0)
83
- .attr('width', sizePix)
84
- .attr('height', sizePix)
85
- .style('fill', this.fillColor)
86
- .style('stroke', this.strokeColor)
87
- .style('stroke-width', this.strokeWidth)
88
- } else if (this.shape === 'circle') {
89
- // <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
90
- const r = (sizePix + this.strokeWidth) * 0.5
91
- svg().append('circle')
92
- .attr('cx', r + 1)
93
- .attr('cy', r + 1)
94
- .attr('r', r)
95
- .style('fill', this.fillColor)
96
- .style('stroke', this.strokeColor)
97
- .style('stroke-width', this.strokeWidth)
98
- } else if (this.shape === 'donut') {
99
- //TODO
100
- } else if (this.shape === 'diamond') {
101
- //TODO
102
- } else if (this.shape === 'line') {
103
-
104
- //get segment length
105
- let lengthPix = this.length ? this.length(opts.resolution, opts.z, opts.viewScale) : opts.resolution
106
- lengthPix /= opts.z
107
-
108
- const svg = d.append('svg').attr('width', lengthPix).attr('height', sizePix).style('', 'inline-block')
109
-
110
- //TODO orientation
111
- //<line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" />
112
- svg.append('line')
113
- .attr('x1', 0)
114
- .attr('y1', sizePix / 2)
115
- .attr('x2', lengthPix)
116
- .attr('y2', sizePix / 2)
117
- .style('stroke', this.color)
118
- .style('stroke-width', sizePix)
119
- } else {
120
- throw new Error('Unexpected shape:' + this.shape)
121
- }
122
-
123
- //label
124
- d.append('div')
125
- .style('display', 'inline')
126
- .style('padding-left', '5px')
127
- .style('font-size', this.labelFontSize)
128
- .text(label + (this.labelUnitText ? ' ' : '') + this.labelUnitText)
129
- }
130
- }
131
-
132
-
133
-
134
-
135
-
136
-
137
-
138
- /**
139
- * @param {Array.<number>} values
140
- * @param {function(number):number} size
141
- * @param { object } opts
142
- * @returns {Array.<SizeLegend>}
143
- */
144
- export function sizeLegend(values, size, opts = {}) {
145
- const legends = []
146
- for (let value of values) {
147
- opts.title = value == values[0] ? opts.title : undefined;
148
- opts.size = () => size(value)
149
- opts.label = () => value
150
- legends.push(new SizeLegend(opts))
151
- }
152
- return legends
153
- }
154
-
155
- /**
156
- * @param { function(import('../core/Dataset.js').Cell):number } value
157
- * @param {*} opts
158
- * @returns {Array.<SizeLegend>}
159
- */
160
- export function sizeLegendViewScale(value, opts = {}) {
161
- const k = opts.k || [0.9, 0.5, 0.2, 0.05]
162
- const legends = []
163
- for (let k_ of k) {
164
- opts.title = k_ == k[0] ? opts.title : undefined
165
- opts.label = (viewScale, cells) => nice(k_ * max(cells, value))
166
- legends.push(new SizeLegend(opts))
167
- }
168
- return legends
169
- }
170
-
171
- /**
172
- * A function which return a stack of size legends for a discrete classification.
173
- *
174
- * @param { Array.<number> } breaks
175
- * @param { Array.<number> } sizes
176
- * @param { object } opts
177
- * @returns {Array.<SizeLegend>}
178
- */
179
- export function sizeDiscreteLegend(breaks, sizes, opts = {}) {
180
- const f = opts.labelFormat || (x => x)
181
- const labelText = opts.labelText || defaultLabelText(f)
182
- const legends = []
183
- for (let i = sizes.length - 1; i >= 0; i--) {
184
- opts.title = i == sizes.length - 1 ? opts.title : undefined
185
- opts.size = () => sizes[i]
186
- opts.label = () => labelText(breaks[i - 1], breaks[i])
187
- legends.push(new SizeLegend(opts))
188
- }
189
- return legends
190
- }
191
-
192
- /**
193
- * A function which return a stack of size legends for a discrete classification using a viewscale.
194
- * @param { number } classNumber
195
- * @param { object } opts
196
- * @returns {Array.<SizeLegend>}
197
- */
198
- export function sizeDiscreteViewScaleLegend(classNumber, opts = {}) {
199
- const f = opts.labelFormat || (x => x)
200
- const labelText = opts.labelText || defaultLabelText(f)
201
- const legends = []
202
- const viewScaleFun = opts.viewScaleFun || (t => t) //TODO do it differently? At sizelegend level !
203
- for (let i = classNumber - 1; i >= 0; i--) {
204
- opts.title = i == classNumber - 1 ? opts.title : undefined
205
- opts.size = (viewScale) => viewScaleFun(viewScale).values[i]
206
- opts.label = (viewScale) => labelText(viewScaleFun(viewScale).breaks[i - 1], viewScaleFun(viewScale).breaks[i])
207
- legends.push(new SizeLegend(opts))
208
- }
209
- return legends
210
- }
211
-
212
- /**
213
- * A function that returns a function to format laberls for discrete scale legends.
214
- * @param { function(number):string } format
215
- * @returns { function(number|undefined, number|undefined): string }
216
- */
217
- function defaultLabelText(format) {
218
- return (v0, v1) => {
219
- if (v0 == undefined && v1 == undefined) return ""
220
- if (v1 == undefined) return "> " + format(v0)
221
- if (v0 == undefined) return "< " + format(v1)
222
- return format(v0) + " - " + format(v1)
223
- }
224
- }
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ import { Legend } from '../core/Legend.js'
5
+ import { nice } from '../utils/utils.js'
6
+ import { max } from 'd3-array'
7
+
8
+ /**
9
+ * A legend element for proportional symbols.
10
+ *
11
+ * @module legend
12
+ * @author Joseph Davies, Julien Gaffuri
13
+ */
14
+ export class SizeLegend extends Legend {
15
+ /** @param {Object} opts */
16
+ constructor(opts) {
17
+ super(opts)
18
+ opts = opts || {}
19
+
20
+ /** A function returning the text label, from the view scale and list of cells, resolution and zoom
21
+ * @type { function(object, Array.<import('../core/Dataset.js').Cell>, number, number):(number|string) } */
22
+ this.label = opts.label || undefined
23
+
24
+ /** A function returning the size of the legend symbol, in geo UoM, from the viewscale, resolution and zoom
25
+ * @type { function(object, number, number):number } */
26
+ this.size = opts.size || undefined
27
+
28
+ //symbol
29
+ /** @type {(import("../core/Style").Shape)|"line"} */
30
+ this.shape = opts.shape || 'circle'
31
+
32
+ //general case
33
+ this.fillColor = opts.fillColor || 'none'
34
+ this.strokeColor = opts.strokeColor || 'gray'
35
+ this.strokeWidth = opts.strokeWidth || 1
36
+
37
+ //for line shape
38
+ //TODO this.orientation = opts.orientation || 0
39
+ this.color = opts.color || 'gray'
40
+ this.length = opts.length || ((resolution, z, viewScale) => resolution)
41
+ }
42
+
43
+ /**
44
+ * @param {{ viewScale:object, resolution: number, z:number, cells:Array.<import('../core/Dataset.js').Cell> }} opts
45
+ */
46
+ update(opts) {
47
+ //clear
48
+ this.div.selectAll('*').remove()
49
+
50
+ //title
51
+ this.makeTitle()
52
+
53
+ //get label. May not be a number (!)
54
+ let label = this.label(opts.viewScale, opts.cells, opts.resolution, opts.z)
55
+
56
+ //compute size of symbol, in pix
57
+ let sizePix
58
+ if (this.size) sizePix = this.size(opts.viewScale, opts.resolution, opts.z) / opts.z
59
+ else sizePix = opts.viewScale(+label) / opts.z
60
+ if (!sizePix) return
61
+
62
+ //format label, if specified and possible
63
+ if (this.labelFormat && !isNaN(+label)) label = this.labelFormat(label)
64
+
65
+ const d = this.div.append('div')
66
+ //to enable vertical centering
67
+ //.style("position", "relative")
68
+
69
+ //default svg construction, for square and circle
70
+ const svg = () =>
71
+ d
72
+ .append('svg')
73
+ .attr('width', sizePix + this.strokeWidth + 2)
74
+ .attr('height', sizePix + this.strokeWidth + 2)
75
+ .style('', 'inline-block')
76
+
77
+ if (this.shape === 'square') {
78
+ svg()
79
+ .append('rect')
80
+ .attr('x', 0)
81
+ .attr('y', 0)
82
+ .attr('width', sizePix)
83
+ .attr('height', sizePix)
84
+ .style('fill', this.fillColor)
85
+ .style('stroke', this.strokeColor)
86
+ .style('stroke-width', this.strokeWidth)
87
+ } else if (this.shape === 'circle') {
88
+ // <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
89
+ const r = (sizePix + this.strokeWidth) * 0.5
90
+ svg()
91
+ .append('circle')
92
+ .attr('cx', r + 1)
93
+ .attr('cy', r + 1)
94
+ .attr('r', r)
95
+ .style('fill', this.fillColor)
96
+ .style('stroke', this.strokeColor)
97
+ .style('stroke-width', this.strokeWidth)
98
+ } else if (this.shape === 'donut') {
99
+ //TODO
100
+ } else if (this.shape === 'diamond') {
101
+ //TODO
102
+ } else if (this.shape === 'line') {
103
+ //get segment length
104
+ let lengthPix = this.length
105
+ ? this.length(opts.resolution, opts.z, opts.viewScale)
106
+ : opts.resolution
107
+ lengthPix /= opts.z
108
+
109
+ const svg = d
110
+ .append('svg')
111
+ .attr('width', lengthPix)
112
+ .attr('height', sizePix)
113
+ .style('', 'inline-block')
114
+
115
+ //TODO orientation
116
+ //<line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" />
117
+ svg.append('line')
118
+ .attr('x1', 0)
119
+ .attr('y1', sizePix / 2)
120
+ .attr('x2', lengthPix)
121
+ .attr('y2', sizePix / 2)
122
+ .style('stroke', this.color)
123
+ .style('stroke-width', sizePix)
124
+ } else {
125
+ throw new Error('Unexpected shape:' + this.shape)
126
+ }
127
+
128
+ //label
129
+ d.append('div')
130
+ .style('display', 'inline')
131
+ .style('padding-left', '5px')
132
+ .style('font-size', this.labelFontSize)
133
+ .text(label + (this.labelUnitText ? ' ' : '') + this.labelUnitText)
134
+ }
135
+ }
136
+
137
+ /**
138
+ * @param {Array.<number>} values
139
+ * @param {function(number):number} size
140
+ * @param { object } opts
141
+ * @returns {Array.<SizeLegend>}
142
+ */
143
+ export function sizeLegend(values, size, opts = {}) {
144
+ const legends = []
145
+ for (let value of values) {
146
+ opts.title = value == values[0] ? opts.title : undefined
147
+ opts.size = () => size(value)
148
+ opts.label = () => value
149
+ legends.push(new SizeLegend(opts))
150
+ }
151
+ return legends
152
+ }
153
+
154
+ /**
155
+ * @param { function(import('../core/Dataset.js').Cell):number } value
156
+ * @param {*} opts
157
+ * @returns {Array.<SizeLegend>}
158
+ */
159
+ export function sizeLegendViewScale(value, opts = {}) {
160
+ const k = opts.k || [0.9, 0.5, 0.2, 0.05]
161
+ const legends = []
162
+ for (let k_ of k) {
163
+ opts.title = k_ == k[0] ? opts.title : undefined
164
+ opts.label = (viewScale, cells) => nice(k_ * max(cells, value))
165
+ legends.push(new SizeLegend(opts))
166
+ }
167
+ return legends
168
+ }
169
+
170
+ /**
171
+ * A function which return a stack of size legends for a discrete classification.
172
+ *
173
+ * @param { Array.<number> } breaks
174
+ * @param { Array.<number> } sizes
175
+ * @param { object } opts
176
+ * @returns {Array.<SizeLegend>}
177
+ */
178
+ export function sizeDiscreteLegend(breaks, sizes, opts = {}) {
179
+ const f = opts.labelFormat || ((x) => x)
180
+ const labelText = opts.labelText || defaultLabelText(f)
181
+ const legends = []
182
+ for (let i = sizes.length - 1; i >= 0; i--) {
183
+ opts.title = i == sizes.length - 1 ? opts.title : undefined
184
+ opts.size = () => sizes[i]
185
+ opts.label = () => labelText(breaks[i - 1], breaks[i])
186
+ legends.push(new SizeLegend(opts))
187
+ }
188
+ return legends
189
+ }
190
+
191
+ /**
192
+ * A function which return a stack of size legends for a discrete classification using a viewscale.
193
+ * @param { number } classNumber
194
+ * @param { object } opts
195
+ * @returns {Array.<SizeLegend>}
196
+ */
197
+ export function sizeDiscreteViewScaleLegend(classNumber, opts = {}) {
198
+ const f = opts.labelFormat || ((x) => x)
199
+ const labelText = opts.labelText || defaultLabelText(f)
200
+ const legends = []
201
+ const viewScaleFun = opts.viewScaleFun || ((t) => t) //TODO do it differently? At sizelegend level !
202
+ for (let i = classNumber - 1; i >= 0; i--) {
203
+ opts.title = i == classNumber - 1 ? opts.title : undefined
204
+ opts.size = (viewScale) => viewScaleFun(viewScale).values[i]
205
+ opts.label = (viewScale) =>
206
+ labelText(viewScaleFun(viewScale).breaks[i - 1], viewScaleFun(viewScale).breaks[i])
207
+ legends.push(new SizeLegend(opts))
208
+ }
209
+ return legends
210
+ }
211
+
212
+ /**
213
+ * A function that returns a function to format laberls for discrete scale legends.
214
+ * @param { function(number):string } format
215
+ * @returns { function(number|undefined, number|undefined): string }
216
+ */
217
+ function defaultLabelText(format) {
218
+ return (v0, v1) => {
219
+ if (v0 == undefined && v1 == undefined) return ''
220
+ if (v1 == undefined) return '> ' + format(v0)
221
+ if (v0 == undefined) return '< ' + format(v1)
222
+ return format(v0) + ' - ' + format(v1)
223
+ }
224
+ }