@abi-software/flatmap-viewer 2.5.0-a.2 → 2.5.2
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.rst +1 -1
- package/package.json +2 -3
- package/src/controls/annotation.js +246 -0
- package/src/controls/controls.js +68 -0
- package/src/controls/minimap.js +3 -8
- package/src/controls/paths3d.js +14 -0
- package/src/flatmap-viewer.js +103 -35
- package/src/interactions.js +187 -49
- package/src/layers/paths3d.js +252 -88
- package/src/main.js +55 -1
- package/src/pathways.js +29 -9
- package/static/css/flatmap-viewer.css +3 -133
package/src/layers/paths3d.js
CHANGED
|
@@ -18,66 +18,133 @@ limitations under the License.
|
|
|
18
18
|
|
|
19
19
|
******************************************************************************/
|
|
20
20
|
|
|
21
|
-
import {colord} from 'colord'
|
|
22
21
|
import {ArcLayer} from '@deck.gl/layers'
|
|
23
22
|
import {MapboxOverlay as DeckOverlay} from '@deck.gl/mapbox'
|
|
24
|
-
import {
|
|
23
|
+
import {Model, Geometry} from '@luma.gl/core'
|
|
24
|
+
import GL from '@luma.gl/constants'
|
|
25
25
|
|
|
26
26
|
//==============================================================================
|
|
27
27
|
|
|
28
|
-
import {
|
|
28
|
+
import {pathColourArray} from '../pathways'
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
//==============================================================================
|
|
31
|
+
|
|
32
|
+
const transparencyCheck = '|| length(vColor) == 0.0'
|
|
33
|
+
|
|
34
|
+
class ArcMapLayer extends ArcLayer
|
|
33
35
|
{
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
static layerName = 'ArcMapLayer'
|
|
37
|
+
|
|
38
|
+
#dirty = false
|
|
39
|
+
#pathData
|
|
40
|
+
|
|
41
|
+
constructor(...args)
|
|
42
|
+
{
|
|
43
|
+
super(...args)
|
|
44
|
+
this.#pathData = new Map([...this.props.data].map(ann => [+ann.featureId, ann]))
|
|
45
|
+
this.#pathData.forEach(ann => delete ann['hidden'])
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
get featureIds()
|
|
49
|
+
//==============
|
|
50
|
+
{
|
|
51
|
+
return [...this.#pathData.keys()]
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
getShaders()
|
|
55
|
+
//==========
|
|
56
|
+
{
|
|
57
|
+
const shaders = super.getShaders()
|
|
58
|
+
shaders.fs = `#version 300 es\n${shaders.fs}`
|
|
59
|
+
.replace('isValid == 0.0', `isValid == 0.0 ${transparencyCheck}`)
|
|
60
|
+
shaders.vs = `#version 300 es\n${shaders.vs}`
|
|
61
|
+
return shaders
|
|
62
|
+
}
|
|
63
|
+
setDataProperty(featureId, key, enabled)
|
|
64
|
+
//======================================
|
|
65
|
+
{
|
|
66
|
+
const properties = this.#pathData.get(+featureId)
|
|
67
|
+
if (properties) {
|
|
68
|
+
if (!(key in properties) || properties[key] !== enabled) {
|
|
69
|
+
properties[key] = enabled
|
|
70
|
+
this.#dirty = true
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
redraw(force=false)
|
|
76
|
+
//=================
|
|
77
|
+
{
|
|
78
|
+
if (force || this.#dirty) {
|
|
79
|
+
this.internalState.changeFlags.dataChanged = true
|
|
80
|
+
this.setNeedsUpdate()
|
|
81
|
+
this.#dirty = false
|
|
82
|
+
}
|
|
83
|
+
}
|
|
36
84
|
}
|
|
37
85
|
|
|
38
86
|
//==============================================================================
|
|
39
87
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
* Dashed paths
|
|
44
|
-
* Control by SCKAN status
|
|
45
|
-
* Control by taxon visibility
|
|
46
|
-
* Control by visible layer
|
|
88
|
+
const makeDashedTriangles = ` float alpha = floor(fract(float(gl_VertexID)/12.0)+0.5);
|
|
89
|
+
if (vColor.a != 0.0) vColor.a *= alpha;
|
|
90
|
+
`
|
|
47
91
|
|
|
92
|
+
class ArcDashedLayer extends ArcMapLayer
|
|
93
|
+
{
|
|
94
|
+
static layerName = 'ArcDashedLayer'
|
|
48
95
|
|
|
49
|
-
|
|
96
|
+
constructor(...args)
|
|
97
|
+
{
|
|
98
|
+
super(...args)
|
|
99
|
+
}
|
|
50
100
|
|
|
101
|
+
getShaders()
|
|
102
|
+
//==========
|
|
103
|
+
{
|
|
104
|
+
const shaders = super.getShaders()
|
|
105
|
+
shaders.vs = shaders.vs.replace('DECKGL_FILTER_COLOR(', `${makeDashedTriangles}\n DECKGL_FILTER_COLOR(`)
|
|
106
|
+
return shaders
|
|
107
|
+
}
|
|
51
108
|
|
|
109
|
+
_getModel(gl)
|
|
110
|
+
//===========
|
|
52
111
|
{
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
112
|
+
const {numSegments} = this.props
|
|
113
|
+
let positions = []
|
|
114
|
+
for (let i = 0; i < numSegments; i++) {
|
|
115
|
+
positions = positions.concat([i, 1, 0, i, -1, 0, i+1, 1, 0,
|
|
116
|
+
i, -1, 0, i+1, 1, 0, i+1, -1, 0])
|
|
117
|
+
}
|
|
118
|
+
const model = new Model(gl, {
|
|
119
|
+
...this.getShaders(),
|
|
120
|
+
id: this.props.id,
|
|
121
|
+
geometry: new Geometry({
|
|
122
|
+
drawMode: GL.TRIANGLES,
|
|
123
|
+
attributes: {
|
|
124
|
+
positions: new Float32Array(positions)
|
|
125
|
+
}
|
|
126
|
+
}),
|
|
127
|
+
isInstanced: true,
|
|
128
|
+
})
|
|
129
|
+
model.setUniforms({numSegments: numSegments})
|
|
130
|
+
return model
|
|
69
131
|
}
|
|
70
|
-
|
|
132
|
+
}
|
|
71
133
|
|
|
72
134
|
//==============================================================================
|
|
73
135
|
|
|
74
136
|
export class Paths3DLayer
|
|
75
137
|
{
|
|
138
|
+
#arcLayers = new Map()
|
|
76
139
|
#deckOverlay = null
|
|
140
|
+
#dimmed = false
|
|
77
141
|
#enabled = false
|
|
142
|
+
#featureToLayer = new Map()
|
|
143
|
+
#knownTypes = []
|
|
78
144
|
#map
|
|
79
145
|
#pathData
|
|
80
146
|
#pathManager
|
|
147
|
+
#pathStyles
|
|
81
148
|
#ui
|
|
82
149
|
|
|
83
150
|
constructor(flatmap, ui)
|
|
@@ -86,85 +153,182 @@ export class Paths3DLayer
|
|
|
86
153
|
this.#map = flatmap.map
|
|
87
154
|
this.#pathManager = ui.pathManager
|
|
88
155
|
this.#pathManager.addWatcher(this.#pathStateChanged.bind(this))
|
|
89
|
-
this.#pathData = [...flatmap.annotations.values()]
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
156
|
+
this.#pathData = new Map([...flatmap.annotations.values()]
|
|
157
|
+
.filter(ann => ann['tile-layer'] === 'pathways'
|
|
158
|
+
&& ann['geometry'] === 'LineString'
|
|
159
|
+
&& 'type' in ann && ann['type'].startsWith('line')
|
|
160
|
+
&& 'kind' in ann
|
|
161
|
+
&& 'pathStartPosition' in ann
|
|
162
|
+
&& 'pathEndPosition' in ann)
|
|
163
|
+
.map(ann => [ann.featureId, ann]))
|
|
164
|
+
this.#pathStyles = new Map(this.#pathManager.pathStyles().map(s => [s.type, s]))
|
|
165
|
+
this.#knownTypes = [...this.#pathStyles.keys()].filter(t => t !== 'other')
|
|
96
166
|
}
|
|
97
167
|
|
|
98
168
|
enable(enable=true)
|
|
99
169
|
//=================
|
|
100
170
|
{
|
|
101
171
|
if (enable && !this.#enabled) {
|
|
102
|
-
this.#
|
|
172
|
+
this.#setupDeckOverlay()
|
|
103
173
|
this.#map.addControl(this.#deckOverlay)
|
|
104
174
|
} else if (!enable && this.#enabled) {
|
|
105
175
|
if (this.#deckOverlay) {
|
|
106
176
|
this.#map.removeControl(this.#deckOverlay)
|
|
177
|
+
this.#deckOverlay.finalize()
|
|
107
178
|
this.#deckOverlay = null
|
|
108
179
|
}
|
|
180
|
+
this.#featureToLayer = new Map()
|
|
109
181
|
}
|
|
110
182
|
this.#enabled = enable
|
|
111
183
|
}
|
|
112
184
|
|
|
113
|
-
|
|
114
|
-
|
|
185
|
+
queryFeaturesAtPoint(point)
|
|
186
|
+
//=========================
|
|
115
187
|
{
|
|
116
188
|
if (this.#deckOverlay) {
|
|
117
|
-
this.#
|
|
118
|
-
|
|
119
|
-
|
|
189
|
+
return this.#deckOverlay
|
|
190
|
+
.pickMultipleObjects(point)
|
|
191
|
+
.map(o => this.#makeMapFeature(o.object))
|
|
192
|
+
}
|
|
193
|
+
return []
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
redraw(force=false)
|
|
197
|
+
//=================
|
|
198
|
+
{
|
|
199
|
+
for (const layer of this.#arcLayers.values()) {
|
|
200
|
+
layer.redraw(force)
|
|
120
201
|
}
|
|
121
202
|
}
|
|
122
203
|
|
|
123
|
-
|
|
204
|
+
removeFeatureState(featureId, key)
|
|
205
|
+
//================================
|
|
206
|
+
{
|
|
207
|
+
const layer = this.#featureToLayer.get(+featureId)
|
|
208
|
+
if (layer) {
|
|
209
|
+
layer.setDataProperty(featureId, key, false)
|
|
210
|
+
layer.redraw()
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
setFeatureState(featureId, state)
|
|
215
|
+
//===============================
|
|
216
|
+
{
|
|
217
|
+
const layer = this.#featureToLayer.get(+featureId)
|
|
218
|
+
if (layer) {
|
|
219
|
+
for (const [key, value] of Object.entries(state)) {
|
|
220
|
+
layer.setDataProperty(featureId, key, value)
|
|
221
|
+
}
|
|
222
|
+
layer.redraw()
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
setPaint(options)
|
|
124
227
|
//===============
|
|
125
228
|
{
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
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
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
229
|
+
const dimmed = options.dimmed || false
|
|
230
|
+
if (this.#dimmed !== dimmed) {
|
|
231
|
+
this.#dimmed = dimmed
|
|
232
|
+
this.redraw(true)
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
#addArcLayer(pathType)
|
|
237
|
+
//====================
|
|
238
|
+
{
|
|
239
|
+
const layer = this.#pathStyles.get(pathType).dashed
|
|
240
|
+
? new ArcDashedLayer(this.#layerOptions(pathType))
|
|
241
|
+
: new ArcMapLayer(this.#layerOptions(pathType))
|
|
242
|
+
layer.featureIds.forEach(id => this.#featureToLayer.set(+id, layer))
|
|
243
|
+
this.#arcLayers.set(pathType, layer)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
#removeArcLayer(pathType)
|
|
247
|
+
//=======================
|
|
248
|
+
{
|
|
249
|
+
const layer = this.#arcLayers.get(pathType)
|
|
250
|
+
if (layer) {
|
|
251
|
+
layer.featureIds.forEach(id => this.#featureToLayer.delete(+id))
|
|
252
|
+
this.#arcLayers.delete(pathType)
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
#pathColour(properties)
|
|
257
|
+
//=====================
|
|
258
|
+
{
|
|
259
|
+
if (properties.hidden) {
|
|
260
|
+
return [0, 0, 0, 0]
|
|
261
|
+
}
|
|
262
|
+
return pathColourArray(properties.kind,
|
|
263
|
+
properties.active || properties.selected ? 255
|
|
264
|
+
: this.#dimmed ? 20 : 160)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
#pathStateChanged(changes={})
|
|
268
|
+
//===========================
|
|
269
|
+
{
|
|
270
|
+
if (this.#deckOverlay) {
|
|
271
|
+
if ('pathType' in changes) {
|
|
272
|
+
const pathType = changes.pathType
|
|
273
|
+
const enabled = this.#pathManager.pathTypeEnabled(pathType)
|
|
274
|
+
if (enabled && !this.#arcLayers.has(pathType)) {
|
|
275
|
+
this.#addArcLayer(pathType)
|
|
276
|
+
} else if (!enabled && this.#arcLayers.has(pathType)) {
|
|
277
|
+
this.#removeArcLayer(pathType)
|
|
278
|
+
}
|
|
279
|
+
this.#deckOverlay.setProps({
|
|
280
|
+
layers: [...this.#arcLayers.values()]
|
|
165
281
|
})
|
|
166
|
-
|
|
167
|
-
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
#layerOptions(pathType)
|
|
288
|
+
//=====================
|
|
289
|
+
{
|
|
290
|
+
const pathData = [...this.#pathData.values()]
|
|
291
|
+
.filter(ann => (this.#knownTypes.includes(ann.kind) && (ann.kind === pathType)
|
|
292
|
+
|| !this.#knownTypes.includes(ann.kind) && (pathType === 'other')))
|
|
293
|
+
return {
|
|
294
|
+
id: `arc-${pathType}`,
|
|
295
|
+
data: pathData,
|
|
296
|
+
pickable: true,
|
|
297
|
+
autoHighlight: true,
|
|
298
|
+
numSegments: 400,
|
|
299
|
+
// Styles
|
|
300
|
+
getSourcePosition: f => f.pathStartPosition,
|
|
301
|
+
getTargetPosition: f => f.pathEndPosition,
|
|
302
|
+
getSourceColor: this.#pathColour.bind(this),
|
|
303
|
+
getTargetColor: this.#pathColour.bind(this),
|
|
304
|
+
highlightColor: o => this.#pathColour(o.object),
|
|
305
|
+
opacity: 1.0,
|
|
306
|
+
getWidth: 3,
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
#makeMapFeature(pickedObject)
|
|
311
|
+
//===========================
|
|
312
|
+
{
|
|
313
|
+
// Mock up a map vector feature
|
|
314
|
+
return {
|
|
315
|
+
id: pickedObject.featureId,
|
|
316
|
+
source: 'vector-tiles',
|
|
317
|
+
sourceLayer: `${pickedObject.layer}_${pickedObject['tile-layer']}`,
|
|
318
|
+
properties: pickedObject,
|
|
319
|
+
arc3dLayer: true
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
#setupDeckOverlay()
|
|
324
|
+
//=================
|
|
325
|
+
{
|
|
326
|
+
[...this.#pathStyles.values()].filter(style => this.#pathManager.pathTypeEnabled(style.type))
|
|
327
|
+
.forEach(style => this.#addArcLayer(style.type))
|
|
328
|
+
this.#deckOverlay = new DeckOverlay({
|
|
329
|
+
layers: [...this.#arcLayers.values()],
|
|
168
330
|
})
|
|
169
331
|
}
|
|
170
332
|
}
|
|
333
|
+
|
|
334
|
+
//==============================================================================
|
package/src/main.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Flatmap viewer and annotation tool
|
|
4
4
|
|
|
5
|
-
Copyright (c) 2019
|
|
5
|
+
Copyright (c) 2019 - 2024 David Brooks
|
|
6
6
|
|
|
7
7
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
8
|
you may not use this file except in compliance with the License.
|
|
@@ -27,6 +27,52 @@ export { MapManager };
|
|
|
27
27
|
|
|
28
28
|
//==============================================================================
|
|
29
29
|
|
|
30
|
+
class DrawControl
|
|
31
|
+
{
|
|
32
|
+
constructor(flatmap)
|
|
33
|
+
{
|
|
34
|
+
this._flatmap = flatmap
|
|
35
|
+
this._lastEvent = null
|
|
36
|
+
this._idField = document.getElementById('drawing-id')
|
|
37
|
+
|
|
38
|
+
this._okBtn = document.getElementById('drawing-ok')
|
|
39
|
+
if (this._okBtn) {
|
|
40
|
+
this._okBtn.addEventListener('click', e => {
|
|
41
|
+
if (this._lastEvent) {
|
|
42
|
+
const feature = this._flatmap.refreshAnnotationFeatureGeometry(this._lastEvent.feature)
|
|
43
|
+
this._flatmap.commitAnnotationEvent(this._lastEvent)
|
|
44
|
+
this._idField.innerText = ''
|
|
45
|
+
this._lastEvent = null
|
|
46
|
+
// Send `feature`, along with user comments, to the annotation service
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
this._cancelBtn = document.getElementById('drawing-cancel')
|
|
52
|
+
if (this._cancelBtn) {
|
|
53
|
+
this._cancelBtn.addEventListener('click', e => {
|
|
54
|
+
if (this._lastEvent) {
|
|
55
|
+
this._flatmap.rollbackAnnotationEvent(this._lastEvent)
|
|
56
|
+
this._idField.innerText = ''
|
|
57
|
+
this._lastEvent = null
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
handleEvent(event)
|
|
64
|
+
//================
|
|
65
|
+
{
|
|
66
|
+
console.log(event)
|
|
67
|
+
if (this._idField) {
|
|
68
|
+
this._idField.innerText = `Annotation ${event.type}, Id: ${event.feature.id}`
|
|
69
|
+
this._lastEvent = event
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
//==============================================================================
|
|
75
|
+
|
|
30
76
|
export async function standaloneViewer(map_endpoint=null, options={})
|
|
31
77
|
{
|
|
32
78
|
const requestUrl = new URL(window.location.href);
|
|
@@ -52,6 +98,7 @@ export async function standaloneViewer(map_endpoint=null, options={})
|
|
|
52
98
|
});
|
|
53
99
|
|
|
54
100
|
let currentMap = null;
|
|
101
|
+
let drawControl = null;
|
|
55
102
|
let defaultBackground = localStorage.getItem('flatmap-background-colour') || 'black';
|
|
56
103
|
|
|
57
104
|
const mapOptions = Object.assign({
|
|
@@ -62,6 +109,7 @@ export async function standaloneViewer(map_endpoint=null, options={})
|
|
|
62
109
|
showId: true,
|
|
63
110
|
showPosition: false,
|
|
64
111
|
standalone: true,
|
|
112
|
+
annotator: true,
|
|
65
113
|
}, options);
|
|
66
114
|
|
|
67
115
|
function loadMap(id, taxon, sex)
|
|
@@ -89,6 +137,8 @@ export async function standaloneViewer(map_endpoint=null, options={})
|
|
|
89
137
|
mapManager.loadMap(id, 'map-canvas', (eventType, ...args) => {
|
|
90
138
|
if (args[0].type === 'control' && args[0].control === 'background') {
|
|
91
139
|
mapOptions.background = args[0].value;
|
|
140
|
+
} else if (eventType === 'annotation') {
|
|
141
|
+
drawControl.handleEvent(...args)
|
|
92
142
|
}
|
|
93
143
|
}, mapOptions)
|
|
94
144
|
.then(map => {
|
|
@@ -98,6 +148,7 @@ export async function standaloneViewer(map_endpoint=null, options={})
|
|
|
98
148
|
map.addMarker('UBERON:0001155'); // Colon
|
|
99
149
|
map.addMarker('UBERON:0001255'); // Bladder
|
|
100
150
|
currentMap = map;
|
|
151
|
+
drawControl = new DrawControl(map)
|
|
101
152
|
})
|
|
102
153
|
.catch(error => {
|
|
103
154
|
console.log(error);
|
|
@@ -179,3 +230,6 @@ export async function standaloneViewer(map_endpoint=null, options={})
|
|
|
179
230
|
|
|
180
231
|
loadMap(mapId, mapTaxon, mapSex);
|
|
181
232
|
}
|
|
233
|
+
|
|
234
|
+
//==============================================================================
|
|
235
|
+
|
package/src/pathways.js
CHANGED
|
@@ -20,6 +20,8 @@ limitations under the License.
|
|
|
20
20
|
|
|
21
21
|
'use strict';
|
|
22
22
|
|
|
23
|
+
import {colord} from 'colord'
|
|
24
|
+
|
|
23
25
|
//==============================================================================
|
|
24
26
|
|
|
25
27
|
import { reverseMap } from './utils';
|
|
@@ -49,15 +51,18 @@ const PATH_TYPES = [
|
|
|
49
51
|
{ type: "error", label: "Paths with errors or warnings", colour: "#FF0", enabled: false}
|
|
50
52
|
];
|
|
51
53
|
|
|
54
|
+
const PathTypeMap = new Map(PATH_TYPES.map(t => [t.type, t]))
|
|
55
|
+
|
|
52
56
|
export const PATH_STYLE_RULES =
|
|
53
57
|
PATH_TYPES.flatMap(pathType => [['==', ['get', 'kind'], pathType.type], pathType.colour]);
|
|
54
58
|
|
|
55
|
-
export
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
export function pathColour(pathType)
|
|
59
|
+
export function pathColourArray(pathType, alpha=255)
|
|
60
|
+
//==================================================
|
|
59
61
|
{
|
|
60
|
-
|
|
62
|
+
const rgb = colord(PathTypeMap.has(pathType)
|
|
63
|
+
? PathTypeMap.get(pathType).colour
|
|
64
|
+
: '#FF0').toRgb()
|
|
65
|
+
return [rgb.r, rgb.g, rgb.b, alpha]
|
|
61
66
|
}
|
|
62
67
|
|
|
63
68
|
//==============================================================================
|
|
@@ -162,6 +167,21 @@ export class PathManager
|
|
|
162
167
|
}
|
|
163
168
|
}
|
|
164
169
|
|
|
170
|
+
pathStyles()
|
|
171
|
+
//==========
|
|
172
|
+
{
|
|
173
|
+
const styles = []
|
|
174
|
+
for (const mapType of this.pathTypes()) {
|
|
175
|
+
const defn = PathTypeMap.get(mapType.type)
|
|
176
|
+
styles.push({
|
|
177
|
+
type: defn.type,
|
|
178
|
+
colour: defn.colour,
|
|
179
|
+
dashed: defn.dashed || false
|
|
180
|
+
})
|
|
181
|
+
}
|
|
182
|
+
return styles
|
|
183
|
+
}
|
|
184
|
+
|
|
165
185
|
pathTypes()
|
|
166
186
|
//=========
|
|
167
187
|
{
|
|
@@ -335,7 +355,7 @@ export class PathManager
|
|
|
335
355
|
this.__ui.enableFeature(featureId, enable, force);
|
|
336
356
|
}
|
|
337
357
|
this.__pathtypeEnabled[pathType] = enable;
|
|
338
|
-
this.#notifyWatchers()
|
|
358
|
+
this.#notifyWatchers({pathType})
|
|
339
359
|
}
|
|
340
360
|
}
|
|
341
361
|
|
|
@@ -390,11 +410,11 @@ export class PathManager
|
|
|
390
410
|
this.#watcherCallbacks.delete(watcherId)
|
|
391
411
|
}
|
|
392
412
|
|
|
393
|
-
#notifyWatchers()
|
|
394
|
-
|
|
413
|
+
#notifyWatchers(changes={})
|
|
414
|
+
//=========================
|
|
395
415
|
{
|
|
396
416
|
for (const callback of this.#watcherCallbacks.values()) {
|
|
397
|
-
callback()
|
|
417
|
+
callback(changes)
|
|
398
418
|
}
|
|
399
419
|
}
|
|
400
420
|
}
|