gridviz 3.0.36 → 3.0.38
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/dist/gridviz.js +8841 -8385
- package/dist/gridviz.min.js +2 -2
- package/package.json +74 -74
- package/src/core/Dataset.js +78 -0
- package/src/core/Legend.js +142 -8
- package/src/core/Map.js +104 -11
- package/src/core/Style.js +48 -0
- package/src/dataset/TiledGrid.js +24 -15
- package/src/layer/GridLayer.js +24 -5
- package/src/legend/ColorCategoryLegend.js +21 -9
- package/src/legend/ColorDiscreteLegend.js +18 -5
- package/src/legend/ColorLegend.js +9 -3
- package/src/legend/OrientationLegend.js +4 -2
- package/src/legend/SizeLegend.js +4 -2
- package/src/legend/TernaryLegend.js +10 -0
- package/src/style/DotDensityStyle.js +3 -3
- package/src/style/ShapeColorSizeStyle.js +4 -0
- package/src/style/SquareColorCategoryWebGLStyle.js +131 -119
- package/src/style/SquareColorWebGLStyle.js +5 -5
- package/src/utils/WebGLSquareColoring.js +28 -32
- package/src/utils/WebGLSquareColoringAdvanced.js +26 -30
- package/src/utils/webGLUtils.js +105 -0
package/src/dataset/TiledGrid.js
CHANGED
|
@@ -55,22 +55,43 @@ export class TiledGrid extends Dataset {
|
|
|
55
55
|
*/
|
|
56
56
|
loadInfo() {
|
|
57
57
|
if (!this.info && this.infoLoadingStatus === 'notLoaded') {
|
|
58
|
+
// marked before the request, so the redraws that happen while it's under way
|
|
59
|
+
// don't request it again
|
|
60
|
+
this.infoLoadingStatus = 'loading'
|
|
58
61
|
;(async () => {
|
|
59
62
|
try {
|
|
60
63
|
const data = await json(this.url + 'info.json')
|
|
61
64
|
this.info = data
|
|
62
65
|
this.resolution = data.resolutionGeo
|
|
63
66
|
this.infoLoadingStatus = 'loaded'
|
|
64
|
-
|
|
67
|
+
// all the resolutions of a multi-resolution dataset load their info at
|
|
68
|
+
// once: only the one currently shown needs a redraw
|
|
69
|
+
if (this.isShown()) this.map.redraw()
|
|
65
70
|
} catch (error) {
|
|
66
71
|
//mark as failed
|
|
67
72
|
this.infoLoadingStatus = 'failed'
|
|
68
73
|
}
|
|
69
74
|
})()
|
|
70
|
-
}
|
|
75
|
+
}
|
|
76
|
+
// (no redraw for a failed info.json: every redraw would ask again - an endless loop)
|
|
71
77
|
return this
|
|
72
78
|
}
|
|
73
79
|
|
|
80
|
+
/**
|
|
81
|
+
* True when a visible layer of the map shows this dataset at the current zoom.
|
|
82
|
+
* @returns {boolean}
|
|
83
|
+
*/
|
|
84
|
+
isShown() {
|
|
85
|
+
if (!this.map || !this.map.layers) return false
|
|
86
|
+
const z = this.map.getZoom()
|
|
87
|
+
for (const lay of this.map.layers) {
|
|
88
|
+
if (lay.visible && !lay.visible(z)) continue
|
|
89
|
+
if (!lay.getDataset) continue
|
|
90
|
+
if (lay.getDataset(z) == this) return true
|
|
91
|
+
}
|
|
92
|
+
return false
|
|
93
|
+
}
|
|
94
|
+
|
|
74
95
|
/**
|
|
75
96
|
* Compute a tiling envelope from a geographical envelope.
|
|
76
97
|
* This is the function to use to know which tiles to download for a geographical view.
|
|
@@ -197,19 +218,7 @@ export class TiledGrid extends Dataset {
|
|
|
197
218
|
// Check if any visible layer depends on this dataset
|
|
198
219
|
// check if redraw is really needed, that is if:
|
|
199
220
|
// 1. the dataset belongs to a layer which is visible at the current zoom level
|
|
200
|
-
|
|
201
|
-
//go through the layers
|
|
202
|
-
const z = this.map.getZoom()
|
|
203
|
-
for (const lay of this.map.layers) {
|
|
204
|
-
if (lay.visible && !lay.visible(z)) continue
|
|
205
|
-
if (!lay.getDataset) continue
|
|
206
|
-
if (lay.getDataset(z) != this) continue
|
|
207
|
-
//found one layer. No need to seek more.
|
|
208
|
-
needsRedraw = true
|
|
209
|
-
break
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
if (!needsRedraw) return
|
|
221
|
+
if (!this.isShown()) return
|
|
213
222
|
|
|
214
223
|
// Check if tile intersects the current view
|
|
215
224
|
const env = this.map.updateExtentGeo()
|
package/src/layer/GridLayer.js
CHANGED
|
@@ -68,6 +68,9 @@ export class GridLayer extends Layer {
|
|
|
68
68
|
if (this.blendOperation) ctx.globalCompositeOperation = this.blendOperation(z)
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
// tell the legends where they are drawn, so that they can fit it (width:'fill')
|
|
72
|
+
if (legend) for (const s of this.styles) GridLayer.setLegendContainer(legend.node(), s.legends, s['styles'])
|
|
73
|
+
|
|
71
74
|
//draw cells, style by style
|
|
72
75
|
for (const s of this.styles) {
|
|
73
76
|
//check if style is visible
|
|
@@ -102,14 +105,14 @@ export class GridLayer extends Layer {
|
|
|
102
105
|
for (const s of this.styles) {
|
|
103
106
|
//check if style is visible
|
|
104
107
|
if (s.visible && !s.visible(z)) continue
|
|
105
|
-
GridLayer.addLegends(legend, s.legends)
|
|
108
|
+
GridLayer.addLegends(legend, s.legends, s, geoCanvas)
|
|
106
109
|
|
|
107
110
|
//case for styles of styles, like kernel smoothing
|
|
108
111
|
//TODO do better
|
|
109
112
|
if (s['styles']) {
|
|
110
113
|
for (const s2 of s['styles']) {
|
|
111
114
|
if (s2.visible && !s2.visible(z)) continue
|
|
112
|
-
GridLayer.addLegends(legend, s2.legends)
|
|
115
|
+
GridLayer.addLegends(legend, s2.legends, s2, geoCanvas)
|
|
113
116
|
}
|
|
114
117
|
}
|
|
115
118
|
}
|
|
@@ -117,9 +120,25 @@ export class GridLayer extends Layer {
|
|
|
117
120
|
}
|
|
118
121
|
|
|
119
122
|
/** @private */
|
|
120
|
-
static
|
|
121
|
-
|
|
122
|
-
|
|
123
|
+
static setLegendContainer(container, legends, subStyles) {
|
|
124
|
+
// legends can be nested in arrays, like in Style.updateLegendsRecursive
|
|
125
|
+
const set = (lg) => {
|
|
126
|
+
if (Array.isArray(lg)) lg.forEach(set)
|
|
127
|
+
else if (lg) lg.container = container
|
|
128
|
+
}
|
|
129
|
+
set(legends)
|
|
130
|
+
for (const s2 of subStyles || []) GridLayer.setLegendContainer(container, s2.legends, undefined)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** @private */
|
|
134
|
+
static addLegends(legendComp, lg, style, geoCanvas) {
|
|
135
|
+
if (Array.isArray(lg)) for (const lg_ of lg) this.addLegends(legendComp, lg_, style, geoCanvas)
|
|
136
|
+
else {
|
|
137
|
+
// so that hovering a swatch can highlight the cells of the style on the map
|
|
138
|
+
lg.style_ = style
|
|
139
|
+
lg.redraw = () => (geoCanvas.redraw ? geoCanvas.redraw() : undefined)
|
|
140
|
+
legendComp.node().append(lg.div.node())
|
|
141
|
+
}
|
|
123
142
|
}
|
|
124
143
|
|
|
125
144
|
/**
|
|
@@ -28,6 +28,7 @@ export class ColorCategoryLegend extends Legend {
|
|
|
28
28
|
this.dimension = opts.dimension || { r: 8 }
|
|
29
29
|
this.strokeColor = opts.strokeColor || 'gray'
|
|
30
30
|
this.strokeWidth = opts.strokeWidth || 1
|
|
31
|
+
this.setType('category')
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
/**
|
|
@@ -47,7 +48,12 @@ export class ColorCategoryLegend extends Legend {
|
|
|
47
48
|
const cat = this.colorLabel[i]
|
|
48
49
|
|
|
49
50
|
//make div for category
|
|
50
|
-
const d = this.div.append('div')
|
|
51
|
+
const d = this.div.append('div').classed('gridviz-legend-category', true)
|
|
52
|
+
// hovering a category shows only its cells on the map
|
|
53
|
+
this.bindHover(d, cat[0], {
|
|
54
|
+
enter: () => d.classed('gridviz-legend-category--active', true).select('svg').select('rect, circle').style('stroke', 'red'),
|
|
55
|
+
leave: () => d.classed('gridviz-legend-category--active', false).select('svg').select('rect, circle').style('stroke', this.strokeColor),
|
|
56
|
+
})
|
|
51
57
|
//to enable vertical centering
|
|
52
58
|
//.style("position", "relative")
|
|
53
59
|
|
|
@@ -65,6 +71,7 @@ export class ColorCategoryLegend extends Legend {
|
|
|
65
71
|
.attr('height', h + 2 * sw)
|
|
66
72
|
|
|
67
73
|
.append('rect')
|
|
74
|
+
.classed('gridviz-legend-swatch', true)
|
|
68
75
|
.attr('x', sw)
|
|
69
76
|
.attr('y', sw)
|
|
70
77
|
.attr('width', w)
|
|
@@ -83,6 +90,7 @@ export class ColorCategoryLegend extends Legend {
|
|
|
83
90
|
.attr('height', h)
|
|
84
91
|
|
|
85
92
|
.append('circle')
|
|
93
|
+
.classed('gridviz-legend-swatch', true)
|
|
86
94
|
.attr('cx', r + sw)
|
|
87
95
|
.attr('cy', r + sw)
|
|
88
96
|
.attr('r', r)
|
|
@@ -94,16 +102,20 @@ export class ColorCategoryLegend extends Legend {
|
|
|
94
102
|
}
|
|
95
103
|
|
|
96
104
|
//write label text
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
105
|
+
this.setText(
|
|
106
|
+
d
|
|
107
|
+
.append('div')
|
|
108
|
+
//show on right of graphic
|
|
109
|
+
.style('display', 'inline')
|
|
100
110
|
|
|
101
|
-
|
|
102
|
-
|
|
111
|
+
//center vertically
|
|
112
|
+
//.style("position", "absolute").style("top", "0").style("bottom", "0")
|
|
103
113
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
114
|
+
.classed('gridviz-legend-label', true)
|
|
115
|
+
.style('padding-left', '5px')
|
|
116
|
+
.style('font-size', this.labelFontSizeCSS()),
|
|
117
|
+
cat[1]
|
|
118
|
+
)
|
|
107
119
|
}
|
|
108
120
|
}
|
|
109
121
|
}
|
|
@@ -21,8 +21,10 @@ export class ColorDiscreteLegend extends Legend {
|
|
|
21
21
|
/** @private @type {function(import('../core/Style').ViewScale):Array.<number>} */
|
|
22
22
|
this.breaks = opts.breaks
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
// a number of pixels, or 'fill' for the width of the container
|
|
25
|
+
this.width = opts.width === 'fill' ? 300 : opts.width || 300
|
|
25
26
|
this.height = opts.height || 15
|
|
27
|
+
this.setType('discrete')
|
|
26
28
|
|
|
27
29
|
this.tickSize = opts.tickSize || 3
|
|
28
30
|
|
|
@@ -48,27 +50,37 @@ export class ColorDiscreteLegend extends Legend {
|
|
|
48
50
|
//classes
|
|
49
51
|
const nb = colors.length
|
|
50
52
|
if (nb == 0) return
|
|
51
|
-
const
|
|
53
|
+
const width = this.availableWidth(this.width)
|
|
54
|
+
const w = width / nb
|
|
52
55
|
|
|
53
56
|
//make svg element
|
|
54
57
|
const svg = this.div
|
|
55
58
|
.append('svg')
|
|
56
|
-
.attr('width',
|
|
59
|
+
.attr('width', width)
|
|
57
60
|
.attr('height', this.height + this.tickSize + 2 + 10)
|
|
58
61
|
|
|
59
62
|
//draw graphic elements
|
|
60
63
|
for (let i = 0; i < nb; i++) {
|
|
61
|
-
svg
|
|
64
|
+
const rect = svg
|
|
65
|
+
.append('rect')
|
|
66
|
+
.classed('gridviz-legend-swatch', true)
|
|
62
67
|
.attr('x', i * w)
|
|
63
68
|
.attr('y', 0)
|
|
64
69
|
.attr('width', w)
|
|
65
70
|
.attr('height', this.height)
|
|
66
71
|
.style('fill', colors[i])
|
|
72
|
+
// hovering a class shows only its cells on the map
|
|
73
|
+
this.bindHover(rect, colors[i], {
|
|
74
|
+
// a presentation attribute, so that a stylesheet can restyle the active swatch
|
|
75
|
+
enter: () => rect.classed('gridviz-legend-swatch--active', true).attr('stroke', 'red'),
|
|
76
|
+
leave: () => rect.classed('gridviz-legend-swatch--active', false).attr('stroke', null),
|
|
77
|
+
})
|
|
67
78
|
}
|
|
68
79
|
|
|
69
80
|
//tick line
|
|
70
81
|
for (let i = 1; i < nb; i++) {
|
|
71
82
|
svg.append('line')
|
|
83
|
+
.classed('gridviz-legend-tick', true)
|
|
72
84
|
.attr('x1', w * i)
|
|
73
85
|
.attr('y1', 0)
|
|
74
86
|
.attr('x2', w * i)
|
|
@@ -84,10 +96,11 @@ export class ColorDiscreteLegend extends Legend {
|
|
|
84
96
|
|
|
85
97
|
//label
|
|
86
98
|
svg.append('text')
|
|
99
|
+
.classed('gridviz-legend-label', true)
|
|
87
100
|
.attr('id', 'ticklabel_' + i)
|
|
88
101
|
.attr('x', w * i)
|
|
89
102
|
.attr('y', this.height + this.tickSize + 2)
|
|
90
|
-
.style('font-size', this.
|
|
103
|
+
.style('font-size', this.labelFontSizeCSS())
|
|
91
104
|
//.style("font-weight", "bold")
|
|
92
105
|
//.style("font-family", "Arial")
|
|
93
106
|
.style('text-anchor', 'middle')
|
|
@@ -35,8 +35,10 @@ export class ColorLegend extends Legend {
|
|
|
35
35
|
this.fontSize = opts.fontSize || '0.8em'
|
|
36
36
|
this.invert = opts.invert
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
// a number of pixels, or 'fill' for the width of the container
|
|
39
|
+
this.width = opts.width === 'fill' ? 300 : opts.width || 300
|
|
39
40
|
this.height = opts.height || 15
|
|
41
|
+
this.setType('color')
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
/**
|
|
@@ -49,7 +51,8 @@ export class ColorLegend extends Legend {
|
|
|
49
51
|
//title
|
|
50
52
|
this.makeTitle()
|
|
51
53
|
|
|
52
|
-
const
|
|
54
|
+
const width = this.availableWidth(this.width)
|
|
55
|
+
const svgW = width + 2 * this.margin
|
|
53
56
|
const svgH = this.height + this.margin + this.tickSize + 10
|
|
54
57
|
const svg = this.div.append('svg').attr('width', svgW).attr('height', svgH)
|
|
55
58
|
// <rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
|
|
@@ -57,13 +60,14 @@ export class ColorLegend extends Legend {
|
|
|
57
60
|
const g = svg.append('g').attr('transform', 'translate(' + this.margin + ' ' + 0 + ')')
|
|
58
61
|
|
|
59
62
|
//draw color bar
|
|
60
|
-
const w =
|
|
63
|
+
const w = width,
|
|
61
64
|
h = this.height
|
|
62
65
|
const step = 5
|
|
63
66
|
for (let i = 0; i < w; i += step) {
|
|
64
67
|
let t = i / (w - 1)
|
|
65
68
|
if (this.invert) t = 1 - t
|
|
66
69
|
g.append('rect')
|
|
70
|
+
.classed('gridviz-legend-swatch', true)
|
|
67
71
|
.attr('x', i)
|
|
68
72
|
.attr('y', 0)
|
|
69
73
|
.attr('width', step)
|
|
@@ -76,6 +80,7 @@ export class ColorLegend extends Legend {
|
|
|
76
80
|
|
|
77
81
|
//tick line
|
|
78
82
|
g.append('line')
|
|
83
|
+
.classed('gridviz-legend-tick', true)
|
|
79
84
|
.attr('x1', w * t)
|
|
80
85
|
.attr('y1', 0)
|
|
81
86
|
.attr('x2', w * t)
|
|
@@ -84,6 +89,7 @@ export class ColorLegend extends Legend {
|
|
|
84
89
|
|
|
85
90
|
//prepare tick label
|
|
86
91
|
g.append('text')
|
|
92
|
+
.classed('gridviz-legend-label', true)
|
|
87
93
|
.attr('id', 'ticklabel_' + i)
|
|
88
94
|
.attr('x', w * t)
|
|
89
95
|
.attr('y', h + this.tickSize + 2)
|
|
@@ -13,6 +13,7 @@ export class OrientationLegend extends Legend {
|
|
|
13
13
|
/** @param {Object} opts */
|
|
14
14
|
constructor(opts) {
|
|
15
15
|
super(opts)
|
|
16
|
+
this.setType('orientation')
|
|
16
17
|
opts = opts || {}
|
|
17
18
|
|
|
18
19
|
//orientation
|
|
@@ -38,7 +39,7 @@ export class OrientationLegend extends Legend {
|
|
|
38
39
|
//title
|
|
39
40
|
this.makeTitle()
|
|
40
41
|
|
|
41
|
-
const d = this.div.append('div')
|
|
42
|
+
const d = this.div.append('div').classed('gridviz-legend-category', true)
|
|
42
43
|
|
|
43
44
|
//compute segment color, width and length
|
|
44
45
|
const color = this.color(opts.resolution, opts.z, opts.viewScale)
|
|
@@ -63,9 +64,10 @@ export class OrientationLegend extends Legend {
|
|
|
63
64
|
|
|
64
65
|
//label
|
|
65
66
|
d.append('div')
|
|
67
|
+
.classed('gridviz-legend-label', true)
|
|
66
68
|
.style('display', 'inline')
|
|
67
69
|
.style('padding-left', '5px')
|
|
68
|
-
.style('font-size', this.
|
|
70
|
+
.style('font-size', this.labelFontSizeCSS())
|
|
69
71
|
.text(this.label + (this.labelUnitText ? ' ' : '') + this.labelUnitText)
|
|
70
72
|
}
|
|
71
73
|
}
|
package/src/legend/SizeLegend.js
CHANGED
|
@@ -15,6 +15,7 @@ export class SizeLegend extends Legend {
|
|
|
15
15
|
/** @param {Object} opts */
|
|
16
16
|
constructor(opts) {
|
|
17
17
|
super(opts)
|
|
18
|
+
this.setType('size')
|
|
18
19
|
opts = opts || {}
|
|
19
20
|
|
|
20
21
|
/** A function returning the text label, from the view scale and list of cells, resolution and zoom
|
|
@@ -62,7 +63,7 @@ export class SizeLegend extends Legend {
|
|
|
62
63
|
//format label, if specified and possible
|
|
63
64
|
if (this.labelFormat && !isNaN(+label)) label = this.labelFormat(label)
|
|
64
65
|
|
|
65
|
-
const d = this.div.append('div')
|
|
66
|
+
const d = this.div.append('div').classed('gridviz-legend-category', true)
|
|
66
67
|
//to enable vertical centering
|
|
67
68
|
//.style("position", "relative")
|
|
68
69
|
|
|
@@ -127,9 +128,10 @@ export class SizeLegend extends Legend {
|
|
|
127
128
|
|
|
128
129
|
//label
|
|
129
130
|
d.append('div')
|
|
131
|
+
.classed('gridviz-legend-label', true)
|
|
130
132
|
.style('display', 'inline')
|
|
131
133
|
.style('padding-left', '5px')
|
|
132
|
-
.style('font-size', this.
|
|
134
|
+
.style('font-size', this.labelFontSizeCSS())
|
|
133
135
|
.text(label + (this.labelUnitText ? ' ' : '') + this.labelUnitText)
|
|
134
136
|
}
|
|
135
137
|
}
|
|
@@ -28,6 +28,7 @@ export class TernaryLegend extends Legend {
|
|
|
28
28
|
this.rightText = opts.rightText || 'Category 2'
|
|
29
29
|
|
|
30
30
|
this.centerCoefficient = opts.centerCoefficient || this.classifier.centerCoefficient
|
|
31
|
+
this.setType('ternary')
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
/**
|
|
@@ -51,6 +52,7 @@ export class TernaryLegend extends Legend {
|
|
|
51
52
|
|
|
52
53
|
const padding = 2
|
|
53
54
|
const fontSize = 12
|
|
55
|
+
const legend = this
|
|
54
56
|
|
|
55
57
|
//make svg element
|
|
56
58
|
const svg = this.div
|
|
@@ -62,6 +64,7 @@ export class TernaryLegend extends Legend {
|
|
|
62
64
|
svg.append('text')
|
|
63
65
|
.attr('x', w / 2)
|
|
64
66
|
.attr('y', padding + fontSize)
|
|
67
|
+
.classed('gridviz-legend-label', true)
|
|
65
68
|
.text(this.topText)
|
|
66
69
|
.attr('font-size', fontSize)
|
|
67
70
|
.attr('text-anchor', 'middle')
|
|
@@ -69,6 +72,7 @@ export class TernaryLegend extends Legend {
|
|
|
69
72
|
svg.append('text')
|
|
70
73
|
.attr('x', 0)
|
|
71
74
|
.attr('y', 3 * padding + 2 * fontSize + h)
|
|
75
|
+
.classed('gridviz-legend-label', true)
|
|
72
76
|
.text(this.leftText)
|
|
73
77
|
.attr('font-size', fontSize)
|
|
74
78
|
.attr('text-anchor', 'start')
|
|
@@ -76,6 +80,7 @@ export class TernaryLegend extends Legend {
|
|
|
76
80
|
svg.append('text')
|
|
77
81
|
.attr('x', w)
|
|
78
82
|
.attr('y', 3 * padding + 2 * fontSize + h)
|
|
83
|
+
.classed('gridviz-legend-label', true)
|
|
79
84
|
.text(this.rightText)
|
|
80
85
|
.attr('font-size', fontSize)
|
|
81
86
|
.attr('text-anchor', 'end')
|
|
@@ -96,12 +101,16 @@ export class TernaryLegend extends Legend {
|
|
|
96
101
|
const setAttributes = (elt, color, text) => {
|
|
97
102
|
//elt.raise();
|
|
98
103
|
elt.attr('fill', color)
|
|
104
|
+
.classed('gridviz-legend-swatch', true)
|
|
99
105
|
//.attr("stroke", colorOver)
|
|
100
106
|
//.attr("stroke-width", 0)
|
|
101
107
|
//.attr("stroke-linejoin", "round")
|
|
108
|
+
.style('cursor', this.interactive ? 'pointer' : null)
|
|
102
109
|
.on('mouseover', function (e) {
|
|
103
110
|
/*this.parentNode.appendChild(this); select(this).attr("stroke-width", selectionStrokeWidth);*/
|
|
104
111
|
select(this).attr('fill', selectionColor)
|
|
112
|
+
// show only the cells of this class on the map
|
|
113
|
+
legend.highlight([color])
|
|
105
114
|
if (!tt || !text) return
|
|
106
115
|
tt.html(text)
|
|
107
116
|
tt.setPosition(e)
|
|
@@ -110,6 +119,7 @@ export class TernaryLegend extends Legend {
|
|
|
110
119
|
.on('mouseout', function () {
|
|
111
120
|
/*select(this).attr("stroke-width", 0);*/
|
|
112
121
|
select(this).attr('fill', color)
|
|
122
|
+
legend.highlight(null)
|
|
113
123
|
if (tt) tt.hide()
|
|
114
124
|
})
|
|
115
125
|
if (tt && text)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import { Style } from '../core/Style.js'
|
|
5
5
|
import { randomNormal } from 'd3-random'
|
|
6
|
-
import { checkWebGLSupport,
|
|
6
|
+
import { checkWebGLSupport, getSharedWebGLCanvas } from '../utils/webGLUtils.js'
|
|
7
7
|
import { WebGLSquareColoring } from '../utils/WebGLSquareColoring.js'
|
|
8
8
|
import { color } from 'd3-color'
|
|
9
9
|
|
|
@@ -62,8 +62,8 @@ export class DotDensityStyle extends Style {
|
|
|
62
62
|
const ctx = geoCanvas.offscreenCtx
|
|
63
63
|
|
|
64
64
|
if (checkWebGLSupport()) {
|
|
65
|
-
//
|
|
66
|
-
const cvWGL =
|
|
65
|
+
//the shared webgl canvas (one context for all styles, instead of a new one per draw)
|
|
66
|
+
const cvWGL = getSharedWebGLCanvas(geoCanvas.w, geoCanvas.h)
|
|
67
67
|
if (!cvWGL) {
|
|
68
68
|
console.error('No webGL')
|
|
69
69
|
return
|
|
@@ -45,6 +45,9 @@ export class ShapeColorSizeStyle extends Style {
|
|
|
45
45
|
|
|
46
46
|
const r2 = resolution * 0.5
|
|
47
47
|
|
|
48
|
+
// the legend swatch hovered, if any: only the cells of its colour are drawn
|
|
49
|
+
const highlight = this.highlightColors
|
|
50
|
+
|
|
48
51
|
// Precompute if color, size, and shape are functions, for efficiency
|
|
49
52
|
const isColorFunction = typeof this.color === 'function'
|
|
50
53
|
const isSizeFunction = typeof this.size === 'function'
|
|
@@ -64,6 +67,7 @@ export class ShapeColorSizeStyle extends Style {
|
|
|
64
67
|
//@ts-ignore
|
|
65
68
|
const col = colorFunction ? colorFunction(c, resolution, z, viewScale) : defaultColor
|
|
66
69
|
if (!col || col === 'none') continue
|
|
70
|
+
if (highlight && !this.isHighlighted(col)) continue
|
|
67
71
|
|
|
68
72
|
// Determine size
|
|
69
73
|
//@ts-ignore
|