gridviz 3.0.22 → 3.0.24
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.
- package/README.md +128 -128
- package/dist/gridviz.js +8618 -8579
- package/dist/gridviz.min.js +1 -1
- package/package.json +74 -74
- package/src/button/Button.js +67 -67
- package/src/button/FullscreenButton.js +121 -121
- package/src/button/ZoomButtons.js +103 -101
- package/src/core/Dataset.js +154 -154
- package/src/core/Drawable.js +78 -78
- package/src/core/GeoCanvas.js +437 -430
- package/src/core/Layer.js +23 -23
- package/src/core/Legend.js +108 -108
- package/src/core/Map.js +542 -516
- package/src/core/MultiResolutionDataset.js +93 -93
- package/src/core/Style.js +98 -98
- package/src/core/Tooltip.js +182 -182
- package/src/dataset/COGeo.js +25 -25
- package/src/dataset/CSVGrid.js +112 -112
- package/src/dataset/GeoTIFF.js +122 -122
- package/src/dataset/JSGrid.js +55 -55
- package/src/dataset/TiledGrid.js +302 -302
- package/src/dataset/worker.js +18 -18
- package/src/index.js +77 -77
- package/src/layer/BackgroundLayer.js +173 -173
- package/src/layer/BackgroundLayerImage.js +81 -81
- package/src/layer/BackgroundLayerWMS.js +104 -104
- package/src/layer/GeoJSONLayer.js +214 -214
- package/src/layer/GridLayer.js +148 -148
- package/src/layer/LabelLayer.js +194 -194
- package/src/legend/ColorCategoryLegend.js +109 -109
- package/src/legend/ColorDiscreteLegend.js +100 -100
- package/src/legend/ColorLegend.js +115 -115
- package/src/legend/OrientationLegend.js +89 -89
- package/src/legend/SizeLegend.js +224 -224
- package/src/legend/TernaryLegend.js +302 -302
- package/src/style/CompositionStyle.js +291 -291
- package/src/style/ContourStyle.js +21 -21
- package/src/style/DotDensityStyle.js +133 -133
- package/src/style/ImageStyle.js +100 -100
- package/src/style/IsoFenceStyle.js +217 -217
- package/src/style/JoyPlotStyle.js +127 -127
- package/src/style/LegoStyle.js +110 -110
- package/src/style/MosaicStyle.js +99 -99
- package/src/style/NinjaStarStyle.js +102 -102
- package/src/style/PillarStyle.js +207 -207
- package/src/style/SegmentStyle.js +105 -105
- package/src/style/ShapeColorSizeStyle.js +147 -147
- package/src/style/SideCategoryStyle.js +112 -112
- package/src/style/SideStyle.js +212 -212
- package/src/style/SquareColorCategoryWebGLStyle.js +107 -107
- package/src/style/SquareColorWebGLStyle.js +126 -126
- package/src/style/StrokeStyle.js +135 -135
- package/src/style/TanakaStyle.js +69 -69
- package/src/style/TextStyle.js +110 -110
- package/src/style/TimeSeriesStyle.js +222 -222
- package/src/utils/WebGLRectangleColoring.js +106 -106
- package/src/utils/WebGLSquareColoring.js +118 -118
- package/src/utils/WebGLSquareColoringAdvanced.js +230 -230
- package/src/utils/WebGLSquareColoringCatAdvanced.js +133 -133
- package/src/utils/WebGLSquareColoringKS.js +153 -153
- package/src/utils/scale.js +218 -218
- package/src/utils/stretching.js +120 -120
- package/src/utils/ternary.js +208 -208
- package/src/utils/utils.js +58 -58
- package/src/utils/webGLUtils.js +72 -72
- package/src/utils/zoomUtils.js +142 -142
package/src/legend/SizeLegend.js
CHANGED
|
@@ -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
|
-
//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
|
-
}
|
|
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
|
+
}
|