gridviz 3.0.15 → 3.0.17
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 +127 -128
- package/dist/gridviz.js +7958 -7861
- package/dist/gridviz.min.js +1 -1
- package/package.json +74 -74
- package/src/button/ZoomButtons.js +101 -96
- package/src/core/Dataset.js +154 -157
- package/src/core/Drawable.js +60 -61
- package/src/core/GeoCanvas.js +409 -370
- package/src/core/Layer.js +23 -25
- package/src/core/Legend.js +108 -110
- package/src/core/Map.js +494 -495
- package/src/core/MultiResolutionDataset.js +93 -97
- package/src/core/Style.js +98 -99
- package/src/dataset/CSVGrid.js +112 -112
- package/src/dataset/GeoTIFF.js +122 -123
- package/src/dataset/JSGrid.js +55 -54
- package/src/dataset/TiledGrid.js +289 -288
- package/src/dataset/worker.js +18 -0
- package/src/index.js +77 -71
- package/src/layer/BackgroundLayer.js +162 -158
- package/src/layer/BackgroundLayerImage.js +81 -84
- package/src/layer/BackgroundLayerWMS.js +104 -108
- package/src/layer/GeoJSONLayer.js +214 -220
- package/src/layer/GridLayer.js +148 -157
- package/src/layer/LabelLayer.js +194 -193
- package/src/legend/ColorCategoryLegend.js +109 -110
- package/src/legend/ColorDiscreteLegend.js +100 -102
- package/src/legend/ColorLegend.js +115 -118
- package/src/legend/OrientationLegend.js +89 -91
- package/src/legend/SizeLegend.js +224 -224
- package/src/legend/TernaryLegend.js +302 -210
- package/src/style/CompositionStyle.js +291 -288
- package/src/style/DotDensityStyle.js +133 -134
- package/src/style/ImageStyle.js +100 -102
- package/src/style/IsoFenceStyle.js +217 -203
- package/src/style/JoyPlotStyle.js +127 -128
- 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 -208
- package/src/style/SegmentStyle.js +105 -105
- package/src/style/ShapeColorSizeStyle.js +147 -132
- package/src/style/SideCategoryStyle.js +112 -114
- package/src/style/SideStyle.js +212 -205
- package/src/style/SquareColorCategoryWebGLStyle.js +107 -108
- package/src/style/SquareColorWebGLStyle.js +126 -126
- package/src/style/StrokeStyle.js +135 -136
- package/src/style/TanakaStyle.js +69 -68
- package/src/style/TextStyle.js +110 -111
- package/src/style/TimeSeriesStyle.js +222 -229
- package/src/utils/scale.js +218 -228
- package/src/utils/stretching.js +120 -133
- package/src/utils/ternary.js +203 -204
- package/src/utils/utils.js +58 -63
- package/src/utils/webGLUtils.js +72 -70
package/src/layer/LabelLayer.js
CHANGED
|
@@ -1,193 +1,194 @@
|
|
|
1
|
-
//@ts-check
|
|
2
|
-
'use strict'
|
|
3
|
-
|
|
4
|
-
import { Layer } from '../core/Layer.js'
|
|
5
|
-
import { csv } from 'd3-fetch'
|
|
6
|
-
|
|
7
|
-
/** A label. The name is the text to show. (x,y) are the coordinates in the same CRS as the grid.
|
|
8
|
-
* @typedef {{name: string, x:number, y:number }} Label */
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* A (generic) layer for placename labels, to be shown on top of the grid layers.
|
|
12
|
-
* The input is a CSV file with the position (x, y) of the labels and name + some other info on the label importance.
|
|
13
|
-
* If the label data is not in the expected format or in the same CRS as the grid, it can be corrected with the "preprocess" function.
|
|
14
|
-
* The selection of the label, their style (font, weight, etc.) and color can be specified depending on their importance and the zoom level.
|
|
15
|
-
*
|
|
16
|
-
* @module layer
|
|
17
|
-
* @author Joseph Davies, Julien Gaffuri
|
|
18
|
-
*/
|
|
19
|
-
export class LabelLayer extends Layer {
|
|
20
|
-
/**
|
|
21
|
-
* @param {object} opts
|
|
22
|
-
*/
|
|
23
|
-
constructor(opts) {
|
|
24
|
-
super(opts)
|
|
25
|
-
opts = opts || {}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* The URL of the label data, as CSV file.
|
|
29
|
-
* The file should contain the information for each label such as the text, the position and other information for the display of the label according to the zoom level.
|
|
30
|
-
* If necessary, this data can be reformated with the 'preprocess' parameter.
|
|
31
|
-
* @private
|
|
32
|
-
* @type {string} */
|
|
33
|
-
this.url = opts.url
|
|
34
|
-
|
|
35
|
-
/** Specify if and how a label should be drawn, depending on its importance and the zoom level.
|
|
36
|
-
* @private
|
|
37
|
-
* @type {function(Label,number):string} */
|
|
38
|
-
this.style = opts.style || (() => 'bold 1em Arial')
|
|
39
|
-
|
|
40
|
-
/** Specify the label color, depending on its importance and the zoom level.
|
|
41
|
-
* @private
|
|
42
|
-
* @type {function(Label,number):string} */
|
|
43
|
-
this.color = opts.color || (opts.dark ? () => '#ddd' : () => '#222')
|
|
44
|
-
|
|
45
|
-
/** Specify the label halo color, depending on its importance and the zoom level.
|
|
46
|
-
* @private
|
|
47
|
-
* @type {function(Label,number):string} */
|
|
48
|
-
this.haloColor = opts.haloColor || (opts.dark ? () => '#000000BB' : () => '#FFFFFFBB')
|
|
49
|
-
|
|
50
|
-
/** Specify the label halo width, depending on its importance and the zoom level.
|
|
51
|
-
* @private
|
|
52
|
-
* @type {function(Label,number):number} */
|
|
53
|
-
this.haloWidth = opts.haloWidth || (() => 4)
|
|
54
|
-
|
|
55
|
-
/** The anchor where to draw the text, from label position. See HTML-canvas textAlign property.
|
|
56
|
-
* "left" || "right" || "center" || "start" || "end"
|
|
57
|
-
* @private
|
|
58
|
-
* @type {CanvasTextAlign} */
|
|
59
|
-
this.textAlign = opts.textAlign || 'start'
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* @private
|
|
63
|
-
* @type {Array.<number>} */
|
|
64
|
-
this.offsetPix = opts.offsetPix || [5, 5]
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* A preprocess to run on each label after loading.
|
|
68
|
-
* It can be used to apply some specific treatment before, format the label data, project coordinates, etc.
|
|
69
|
-
* Return false if the label should not be kept.
|
|
70
|
-
* @private
|
|
71
|
-
* @type {function(Label):boolean} */
|
|
72
|
-
this.preprocess = opts.preprocess
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* @private
|
|
76
|
-
* @type {Array.<Label> | undefined} */
|
|
77
|
-
this.labels = undefined
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* @private
|
|
81
|
-
* @type {string} */
|
|
82
|
-
this.loadingStatus = 'notLoaded'
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Draw the label layer.
|
|
87
|
-
*
|
|
88
|
-
* @param {import("../core/GeoCanvas").GeoCanvas} geoCanvas The canvas where to draw the layer.
|
|
89
|
-
* @returns {void}
|
|
90
|
-
*/
|
|
91
|
-
draw(geoCanvas) {
|
|
92
|
-
//load labels, if not done yet.
|
|
93
|
-
if (!this.labels) {
|
|
94
|
-
this.load(geoCanvas.redraw)
|
|
95
|
-
return
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
//
|
|
99
|
-
const z = geoCanvas.view.z
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
*
|
|
150
|
-
* @
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
this.
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
this.
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
1
|
+
//@ts-check
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
import { Layer } from '../core/Layer.js'
|
|
5
|
+
import { csv } from 'd3-fetch'
|
|
6
|
+
|
|
7
|
+
/** A label. The name is the text to show. (x,y) are the coordinates in the same CRS as the grid.
|
|
8
|
+
* @typedef {{name: string, x:number, y:number }} Label */
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A (generic) layer for placename labels, to be shown on top of the grid layers.
|
|
12
|
+
* The input is a CSV file with the position (x, y) of the labels and name + some other info on the label importance.
|
|
13
|
+
* If the label data is not in the expected format or in the same CRS as the grid, it can be corrected with the "preprocess" function.
|
|
14
|
+
* The selection of the label, their style (font, weight, etc.) and color can be specified depending on their importance and the zoom level.
|
|
15
|
+
*
|
|
16
|
+
* @module layer
|
|
17
|
+
* @author Joseph Davies, Julien Gaffuri
|
|
18
|
+
*/
|
|
19
|
+
export class LabelLayer extends Layer {
|
|
20
|
+
/**
|
|
21
|
+
* @param {object} opts
|
|
22
|
+
*/
|
|
23
|
+
constructor(opts) {
|
|
24
|
+
super(opts)
|
|
25
|
+
opts = opts || {}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The URL of the label data, as CSV file.
|
|
29
|
+
* The file should contain the information for each label such as the text, the position and other information for the display of the label according to the zoom level.
|
|
30
|
+
* If necessary, this data can be reformated with the 'preprocess' parameter.
|
|
31
|
+
* @private
|
|
32
|
+
* @type {string} */
|
|
33
|
+
this.url = opts.url
|
|
34
|
+
|
|
35
|
+
/** Specify if and how a label should be drawn, depending on its importance and the zoom level.
|
|
36
|
+
* @private
|
|
37
|
+
* @type {function(Label,number):string} */
|
|
38
|
+
this.style = opts.style || (() => 'bold 1em Arial')
|
|
39
|
+
|
|
40
|
+
/** Specify the label color, depending on its importance and the zoom level.
|
|
41
|
+
* @private
|
|
42
|
+
* @type {function(Label,number):string} */
|
|
43
|
+
this.color = opts.color || (opts.dark ? () => '#ddd' : () => '#222')
|
|
44
|
+
|
|
45
|
+
/** Specify the label halo color, depending on its importance and the zoom level.
|
|
46
|
+
* @private
|
|
47
|
+
* @type {function(Label,number):string} */
|
|
48
|
+
this.haloColor = opts.haloColor || (opts.dark ? () => '#000000BB' : () => '#FFFFFFBB')
|
|
49
|
+
|
|
50
|
+
/** Specify the label halo width, depending on its importance and the zoom level.
|
|
51
|
+
* @private
|
|
52
|
+
* @type {function(Label,number):number} */
|
|
53
|
+
this.haloWidth = opts.haloWidth || (() => 4)
|
|
54
|
+
|
|
55
|
+
/** The anchor where to draw the text, from label position. See HTML-canvas textAlign property.
|
|
56
|
+
* "left" || "right" || "center" || "start" || "end"
|
|
57
|
+
* @private
|
|
58
|
+
* @type {CanvasTextAlign} */
|
|
59
|
+
this.textAlign = opts.textAlign || 'start'
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @private
|
|
63
|
+
* @type {Array.<number>} */
|
|
64
|
+
this.offsetPix = opts.offsetPix || [5, 5]
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* A preprocess to run on each label after loading.
|
|
68
|
+
* It can be used to apply some specific treatment before, format the label data, project coordinates, etc.
|
|
69
|
+
* Return false if the label should not be kept.
|
|
70
|
+
* @private
|
|
71
|
+
* @type {function(Label):boolean} */
|
|
72
|
+
this.preprocess = opts.preprocess
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @private
|
|
76
|
+
* @type {Array.<Label> | undefined} */
|
|
77
|
+
this.labels = undefined
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @private
|
|
81
|
+
* @type {string} */
|
|
82
|
+
this.loadingStatus = 'notLoaded'
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Draw the label layer.
|
|
87
|
+
*
|
|
88
|
+
* @param {import("../core/GeoCanvas").GeoCanvas} geoCanvas The canvas where to draw the layer.
|
|
89
|
+
* @returns {void}
|
|
90
|
+
*/
|
|
91
|
+
draw(geoCanvas) {
|
|
92
|
+
//load labels, if not done yet.
|
|
93
|
+
if (!this.labels) {
|
|
94
|
+
this.load(geoCanvas.redraw)
|
|
95
|
+
return
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
//
|
|
99
|
+
const z = geoCanvas.view.z
|
|
100
|
+
const ctx = geoCanvas.offscreenCtx
|
|
101
|
+
|
|
102
|
+
//text align
|
|
103
|
+
ctx.textAlign = this.textAlign || 'start'
|
|
104
|
+
|
|
105
|
+
//line join and cap
|
|
106
|
+
ctx.lineJoin = 'bevel' //|| "round" || "miter";
|
|
107
|
+
ctx.lineCap = 'butt' //|| "round" || "square";
|
|
108
|
+
|
|
109
|
+
//draw in pix coordinates
|
|
110
|
+
geoCanvas.initCanvasTransform()
|
|
111
|
+
|
|
112
|
+
//draw labels, one by one
|
|
113
|
+
for (const lb of this.labels) {
|
|
114
|
+
//get label style
|
|
115
|
+
const st = this.style(lb, z)
|
|
116
|
+
if (!st) continue
|
|
117
|
+
ctx.font = st
|
|
118
|
+
|
|
119
|
+
//check label within the view, to be drawn
|
|
120
|
+
if (!geoCanvas.toDraw(lb)) continue
|
|
121
|
+
|
|
122
|
+
//position
|
|
123
|
+
const xP = geoCanvas.geoToPixX(lb.x) + this.offsetPix[0]
|
|
124
|
+
const yP = geoCanvas.geoToPixY(lb.y) - this.offsetPix[1]
|
|
125
|
+
|
|
126
|
+
//label stroke, for the halo
|
|
127
|
+
if (this.haloColor && this.haloWidth) {
|
|
128
|
+
const hc = this.haloColor(lb, z)
|
|
129
|
+
const hw = this.haloWidth(lb, z)
|
|
130
|
+
if (hc && hw && hw > 0) {
|
|
131
|
+
ctx.strokeStyle = hc
|
|
132
|
+
ctx.lineWidth = hw
|
|
133
|
+
ctx.strokeText(lb.name, xP, yP)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
//label fill
|
|
138
|
+
if (this.color) {
|
|
139
|
+
const col = this.color(lb, z)
|
|
140
|
+
if (col) {
|
|
141
|
+
ctx.fillStyle = col
|
|
142
|
+
ctx.fillText(lb.name, xP, yP)
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Load data for labels, from URL this.url
|
|
150
|
+
* @param {function():void} callback
|
|
151
|
+
* @private
|
|
152
|
+
*/
|
|
153
|
+
async load(callback) {
|
|
154
|
+
if (!this.url) {
|
|
155
|
+
console.log('Failed loading labels: No URL specified. ' + this.url)
|
|
156
|
+
this.loadingStatus = 'failed'
|
|
157
|
+
this.labels = []
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
//check if data already loaded
|
|
162
|
+
if (this.loadingStatus != 'notLoaded') return
|
|
163
|
+
|
|
164
|
+
//load data
|
|
165
|
+
this.loadingStatus = 'loading'
|
|
166
|
+
|
|
167
|
+
try {
|
|
168
|
+
/** @type { Array.<Label> } */
|
|
169
|
+
const data = await csv(this.url)
|
|
170
|
+
|
|
171
|
+
//preprocess/filter
|
|
172
|
+
if (this.preprocess) {
|
|
173
|
+
this.labels = []
|
|
174
|
+
for (const c of data) {
|
|
175
|
+
const b = this.preprocess(c)
|
|
176
|
+
if (b == false) continue
|
|
177
|
+
this.labels.push(c)
|
|
178
|
+
}
|
|
179
|
+
} else {
|
|
180
|
+
//store labels
|
|
181
|
+
this.labels = data
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
this.loadingStatus = 'loaded'
|
|
185
|
+
|
|
186
|
+
//redraw
|
|
187
|
+
if (callback) callback()
|
|
188
|
+
} catch (error) {
|
|
189
|
+
console.log('Failed loading labels from ' + this.url)
|
|
190
|
+
this.labels = []
|
|
191
|
+
this.loadingStatus = 'failed'
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -1,110 +1,109 @@
|
|
|
1
|
-
//@ts-check
|
|
2
|
-
'use strict'
|
|
3
|
-
|
|
4
|
-
import { Legend } from '../core/Legend.js'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* A legend element for color categrories.
|
|
8
|
-
*
|
|
9
|
-
* @module legend
|
|
10
|
-
* @author Joseph Davies, Julien Gaffuri
|
|
11
|
-
*/
|
|
12
|
-
export class ColorCategoryLegend extends Legend {
|
|
13
|
-
/** @param {Object} opts */
|
|
14
|
-
constructor(opts) {
|
|
15
|
-
super(opts)
|
|
16
|
-
opts = opts || {}
|
|
17
|
-
|
|
18
|
-
//col/categories array, in display order
|
|
19
|
-
/**
|
|
20
|
-
* @private
|
|
21
|
-
* @type {Array.<[string,string]>} */
|
|
22
|
-
this.colorLabel = opts.colorLabel || [['gray', '-']]
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* @private
|
|
26
|
-
* @type {import("../core/Style.js").Shape} */
|
|
27
|
-
this.shape = opts.shape || 'circle'
|
|
28
|
-
this.dimension = opts.dimension || { r: 8 }
|
|
29
|
-
this.strokeColor = opts.strokeColor || 'gray'
|
|
30
|
-
this.strokeWidth = opts.strokeWidth || 1
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
*/
|
|
35
|
-
update() {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
.
|
|
65
|
-
.attr('
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
.
|
|
69
|
-
.attr('
|
|
70
|
-
.attr('
|
|
71
|
-
.attr('
|
|
72
|
-
.
|
|
73
|
-
.style('
|
|
74
|
-
.style('stroke', this.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
.
|
|
83
|
-
.attr('
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
.
|
|
87
|
-
.attr('
|
|
88
|
-
.attr('
|
|
89
|
-
.
|
|
90
|
-
.style('
|
|
91
|
-
.style('stroke', this.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
.style('
|
|
106
|
-
.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
1
|
+
//@ts-check
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
import { Legend } from '../core/Legend.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A legend element for color categrories.
|
|
8
|
+
*
|
|
9
|
+
* @module legend
|
|
10
|
+
* @author Joseph Davies, Julien Gaffuri
|
|
11
|
+
*/
|
|
12
|
+
export class ColorCategoryLegend extends Legend {
|
|
13
|
+
/** @param {Object} opts */
|
|
14
|
+
constructor(opts) {
|
|
15
|
+
super(opts)
|
|
16
|
+
opts = opts || {}
|
|
17
|
+
|
|
18
|
+
//col/categories array, in display order
|
|
19
|
+
/**
|
|
20
|
+
* @private
|
|
21
|
+
* @type {Array.<[string,string]>} */
|
|
22
|
+
this.colorLabel = opts.colorLabel || [['gray', '-']]
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @private
|
|
26
|
+
* @type {import("../core/Style.js").Shape} */
|
|
27
|
+
this.shape = opts.shape || 'circle'
|
|
28
|
+
this.dimension = opts.dimension || { r: 8 }
|
|
29
|
+
this.strokeColor = opts.strokeColor || 'gray'
|
|
30
|
+
this.strokeWidth = opts.strokeWidth || 1
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
*/
|
|
35
|
+
update() {
|
|
36
|
+
//clear
|
|
37
|
+
this.div.selectAll('*').remove()
|
|
38
|
+
|
|
39
|
+
//title
|
|
40
|
+
this.makeTitle()
|
|
41
|
+
|
|
42
|
+
//categories
|
|
43
|
+
const nb = this.colorLabel.length
|
|
44
|
+
if (nb == 0) return
|
|
45
|
+
|
|
46
|
+
for (let i = 0; i < nb; i++) {
|
|
47
|
+
const cat = this.colorLabel[i]
|
|
48
|
+
|
|
49
|
+
//make div for category
|
|
50
|
+
const d = this.div.append('div')
|
|
51
|
+
//to enable vertical centering
|
|
52
|
+
//.style("position", "relative")
|
|
53
|
+
|
|
54
|
+
const sw = this.strokeWidth
|
|
55
|
+
|
|
56
|
+
//draw graphic element: box / circle
|
|
57
|
+
if (this.shape === 'square') {
|
|
58
|
+
const h = this.dimension.h || 15
|
|
59
|
+
const w = this.dimension.w || 20
|
|
60
|
+
d.append('div')
|
|
61
|
+
.style('display', 'inline')
|
|
62
|
+
|
|
63
|
+
.append('svg')
|
|
64
|
+
.attr('width', w + 2 * sw)
|
|
65
|
+
.attr('height', h + 2 * sw)
|
|
66
|
+
|
|
67
|
+
.append('rect')
|
|
68
|
+
.attr('x', sw)
|
|
69
|
+
.attr('y', sw)
|
|
70
|
+
.attr('width', w)
|
|
71
|
+
.attr('height', h)
|
|
72
|
+
.style('fill', cat[0])
|
|
73
|
+
.style('stroke', this.strokeColor)
|
|
74
|
+
.style('stroke-width', this.strokeWidth)
|
|
75
|
+
} else if (this.shape === 'circle') {
|
|
76
|
+
const r = this.dimension.r || 8
|
|
77
|
+
const h = 2 * r + 2 * sw
|
|
78
|
+
d.append('div')
|
|
79
|
+
.style('display', 'inline')
|
|
80
|
+
|
|
81
|
+
.append('svg')
|
|
82
|
+
.attr('width', h)
|
|
83
|
+
.attr('height', h)
|
|
84
|
+
|
|
85
|
+
.append('circle')
|
|
86
|
+
.attr('cx', r + sw)
|
|
87
|
+
.attr('cy', r + sw)
|
|
88
|
+
.attr('r', r)
|
|
89
|
+
.style('fill', cat[0])
|
|
90
|
+
.style('stroke', this.strokeColor)
|
|
91
|
+
.style('stroke-width', this.strokeWidth)
|
|
92
|
+
} else {
|
|
93
|
+
throw new Error('Unexpected shape:' + this.shape)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
//write label text
|
|
97
|
+
d.append('div')
|
|
98
|
+
//show on right of graphic
|
|
99
|
+
.style('display', 'inline')
|
|
100
|
+
|
|
101
|
+
//center vertically
|
|
102
|
+
//.style("position", "absolute").style("top", "0").style("bottom", "0")
|
|
103
|
+
|
|
104
|
+
.style('padding-left', '5px')
|
|
105
|
+
.style('font-size', this.labelFontSize)
|
|
106
|
+
.text(cat[1])
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|