@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/README.rst
CHANGED
|
@@ -38,7 +38,7 @@ The map server endpoint is specified as ``MAP_ENDPOINT`` in ``src/main.js``. It
|
|
|
38
38
|
Package Installation
|
|
39
39
|
====================
|
|
40
40
|
|
|
41
|
-
* ``npm install @abi-software/flatmap-viewer@2.5.
|
|
41
|
+
* ``npm install @abi-software/flatmap-viewer@2.5.2``
|
|
42
42
|
|
|
43
43
|
Documentation
|
|
44
44
|
-------------
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abi-software/flatmap-viewer",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.2",
|
|
4
4
|
"description": "Flatmap viewer using Maplibre GL",
|
|
5
5
|
"repository": "https://github.com/AnatomicMaps/flatmap-viewer.git",
|
|
6
6
|
"main": "src/main.js",
|
|
@@ -19,10 +19,9 @@
|
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@babel/runtime": "^7.10.4",
|
|
21
21
|
"@deck.gl/core": "^8.9.33",
|
|
22
|
-
"@deck.gl/extensions": "^8.9.34",
|
|
23
22
|
"@deck.gl/layers": "^8.9.33",
|
|
24
23
|
"@deck.gl/mapbox": "^8.9.33",
|
|
25
|
-
"@
|
|
24
|
+
"@mapbox/mapbox-gl-draw": "^1.4.3",
|
|
26
25
|
"@turf/area": "^6.5.0",
|
|
27
26
|
"@turf/bbox": "^6.5.0",
|
|
28
27
|
"@turf/helpers": "^6.5.0",
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/******************************************************************************
|
|
2
|
+
|
|
3
|
+
Flatmap viewer and annotation tool
|
|
4
|
+
|
|
5
|
+
Copyright (c) 2019 - 2023 David Brooks
|
|
6
|
+
|
|
7
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
you may not use this file except in compliance with the License.
|
|
9
|
+
You may obtain a copy of the License at
|
|
10
|
+
|
|
11
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
|
|
13
|
+
Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
See the License for the specific language governing permissions and
|
|
17
|
+
limitations under the License.
|
|
18
|
+
|
|
19
|
+
**/
|
|
20
|
+
|
|
21
|
+
/*
|
|
22
|
+
* Annotation drawing mode is enabled/disabled by:
|
|
23
|
+
*
|
|
24
|
+
* 1. A call to ``Flatmap.enableAnnotation()``
|
|
25
|
+
* 2. An on-map control button calls this when in standalone viewing mode.
|
|
26
|
+
*
|
|
27
|
+
* Drawn features include a GeoJSON geometry. Existing geometries of annotated
|
|
28
|
+
* features are added to the MapboxDraw control when the map is loaded. These
|
|
29
|
+
* should only be visible on the map when the draw control is active.
|
|
30
|
+
*
|
|
31
|
+
* We listen for drawn features being created, updated and deleted, and notify
|
|
32
|
+
* the external annotator, first assigning new features and ID wrt the flatmap.
|
|
33
|
+
* The external annotator may reject a new feature (the user's cancelled the
|
|
34
|
+
* resulting dialog) which results in the newly drawn feature being removed from
|
|
35
|
+
* the control.
|
|
36
|
+
*
|
|
37
|
+
* The external annotator is responsible for saving/obtaining drawn geometries
|
|
38
|
+
* from an annotation service.
|
|
39
|
+
*
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
//==============================================================================
|
|
43
|
+
|
|
44
|
+
import MapboxDraw from "@mapbox/mapbox-gl-draw"
|
|
45
|
+
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css'
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
//==============================================================================
|
|
49
|
+
|
|
50
|
+
const drawStyleIds = MapboxDraw.lib.theme.map(s => s.id)
|
|
51
|
+
|
|
52
|
+
export const DRAW_ANNOTATION_LAYERS = [...drawStyleIds.map(id => `${id}.cold`),
|
|
53
|
+
...drawStyleIds.map(id => `${id}.hot`)]
|
|
54
|
+
|
|
55
|
+
//==============================================================================
|
|
56
|
+
|
|
57
|
+
export class AnnotationDrawControl
|
|
58
|
+
{
|
|
59
|
+
constructor(flatmap, visible=false)
|
|
60
|
+
{
|
|
61
|
+
MapboxDraw.constants.classes.CONTROL_BASE = 'maplibregl-ctrl'
|
|
62
|
+
MapboxDraw.constants.classes.CONTROL_PREFIX = 'maplibregl-ctrl-'
|
|
63
|
+
MapboxDraw.constants.classes.CONTROL_GROUP = 'maplibregl-ctrl-group'
|
|
64
|
+
|
|
65
|
+
this.__flatmap = flatmap
|
|
66
|
+
this.__committedFeatures = new Map()
|
|
67
|
+
this.__uncommittedFeatureIds = new Set()
|
|
68
|
+
this.__visible = visible
|
|
69
|
+
this.__draw = new MapboxDraw({
|
|
70
|
+
displayControlsDefault: false,
|
|
71
|
+
controls: {
|
|
72
|
+
point: true,
|
|
73
|
+
line_string: true,
|
|
74
|
+
polygon: true,
|
|
75
|
+
trash: true
|
|
76
|
+
},
|
|
77
|
+
userProperties: true,
|
|
78
|
+
keybindings: true
|
|
79
|
+
})
|
|
80
|
+
this.__map = null
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
onAdd(map)
|
|
84
|
+
//========
|
|
85
|
+
{
|
|
86
|
+
this.__map = map
|
|
87
|
+
this.__container = this.__draw.onAdd(map)
|
|
88
|
+
|
|
89
|
+
// Fix to allow deletion with Del Key when default trash icon is not shown.
|
|
90
|
+
// See https://github.com/mapbox/mapbox-gl-draw/issues/989
|
|
91
|
+
this.__draw.options.controls.trash = true
|
|
92
|
+
|
|
93
|
+
// Prevent firefox menu from appearing on Alt key up
|
|
94
|
+
window.addEventListener('keyup', function (e) {
|
|
95
|
+
if (e.key === "Alt") {
|
|
96
|
+
e.preventDefault();
|
|
97
|
+
}
|
|
98
|
+
}, false)
|
|
99
|
+
map.on('draw.create', this.createdFeature.bind(this))
|
|
100
|
+
map.on('draw.delete', this.deletedFeature.bind(this))
|
|
101
|
+
map.on('draw.update', this.updatedFeature.bind(this))
|
|
102
|
+
this.show(this.__visible)
|
|
103
|
+
return this.__container
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
onRemove()
|
|
107
|
+
//========
|
|
108
|
+
{
|
|
109
|
+
this.__container.parentNode.removeChild(this.__container)
|
|
110
|
+
this.__container = null
|
|
111
|
+
this.__map = null
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
show(visible=true)
|
|
115
|
+
//================
|
|
116
|
+
{
|
|
117
|
+
if (this.__container) {
|
|
118
|
+
this.__container.style.display = visible ? 'block' : 'none'
|
|
119
|
+
if (visible && !this.__visible) {
|
|
120
|
+
for (const layerId of DRAW_ANNOTATION_LAYERS) {
|
|
121
|
+
this.__map.setLayoutProperty(layerId, 'visibility', 'visible')
|
|
122
|
+
}
|
|
123
|
+
} else if (!visible && this.__visible) {
|
|
124
|
+
for (const layerId of DRAW_ANNOTATION_LAYERS) {
|
|
125
|
+
this.__map.setLayoutProperty(layerId, 'visibility', 'none')
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
this.__visible = visible
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
#cleanFeature(event)
|
|
133
|
+
//==================
|
|
134
|
+
{
|
|
135
|
+
const features = event.features.filter(f => f.type === 'Feature')
|
|
136
|
+
.map(f => {
|
|
137
|
+
return {
|
|
138
|
+
id: f.id,
|
|
139
|
+
type: 'Feature',
|
|
140
|
+
geometry: f.geometry
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
return features.length ? features[0] : null
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
#sendEvent(type, feature)
|
|
147
|
+
//=======================
|
|
148
|
+
{
|
|
149
|
+
this.__uncommittedFeatureIds.add(feature.id)
|
|
150
|
+
this.__flatmap.annotationEvent(type, feature)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
createdFeature(event)
|
|
154
|
+
//===================
|
|
155
|
+
{
|
|
156
|
+
const feature = this.#cleanFeature(event)
|
|
157
|
+
if (feature) {
|
|
158
|
+
// Set properties to indicate that this is a drawn annotation
|
|
159
|
+
this.__draw.setFeatureProperty(feature.id, 'drawn', true)
|
|
160
|
+
this.__draw.setFeatureProperty(feature.id, 'label', 'Drawn annotation')
|
|
161
|
+
// They need to be on the feature passed to the annotator for storage
|
|
162
|
+
feature.properties = {
|
|
163
|
+
user_drawn: true,
|
|
164
|
+
user_label: 'Drawn annotation'
|
|
165
|
+
}
|
|
166
|
+
this.#sendEvent('created', feature)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
deletedFeature(event)
|
|
171
|
+
//===================
|
|
172
|
+
{
|
|
173
|
+
const feature = this.#cleanFeature(event)
|
|
174
|
+
if (feature) {
|
|
175
|
+
if (this.__uncommittedFeatureIds.has(feature.id)) {
|
|
176
|
+
// Ignore delete on an uncommitted create or update
|
|
177
|
+
} else {
|
|
178
|
+
this.#sendEvent('deleted', feature)
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
updatedFeature(event)
|
|
184
|
+
//===================
|
|
185
|
+
{
|
|
186
|
+
const feature = this.#cleanFeature(event)
|
|
187
|
+
if (feature) {
|
|
188
|
+
if (this.__uncommittedFeatureIds.has(feature.id)) {
|
|
189
|
+
// Ignore updates on an uncommitted create or update
|
|
190
|
+
} else {
|
|
191
|
+
this.#sendEvent('updated', feature)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
commitEvent(event)
|
|
197
|
+
//================
|
|
198
|
+
{
|
|
199
|
+
const feature = event.feature
|
|
200
|
+
if (event.type === 'deleted') {
|
|
201
|
+
this.__committedFeatures.delete(feature.id)
|
|
202
|
+
} else {
|
|
203
|
+
this.__committedFeatures.set(feature.id, feature)
|
|
204
|
+
}
|
|
205
|
+
this.__uncommittedFeatureIds.delete(feature.id)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
rollbackEvent(event)
|
|
209
|
+
//==================
|
|
210
|
+
{
|
|
211
|
+
const feature = event.feature
|
|
212
|
+
if (event.type === 'created') {
|
|
213
|
+
this.__draw.delete(feature.id)
|
|
214
|
+
this.__committedFeatures.delete(feature.id)
|
|
215
|
+
this.__uncommittedFeatureIds.delete(feature.id)
|
|
216
|
+
} else if (event.type === 'deleted') {
|
|
217
|
+
this.__draw.add(feature)
|
|
218
|
+
this.__committedFeatures.set(feature.id, feature)
|
|
219
|
+
this.__uncommittedFeatureIds.delete(feature.id)
|
|
220
|
+
} else if (event.type === 'updated') {
|
|
221
|
+
const savedFeature = this.__committedFeatures.get(feature.id)
|
|
222
|
+
if (savedFeature) {
|
|
223
|
+
this.__draw.delete(feature.id)
|
|
224
|
+
this.__draw.add(savedFeature)
|
|
225
|
+
this.__uncommittedFeatureIds.delete(feature.id)
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
addFeature(feature)
|
|
231
|
+
//=================
|
|
232
|
+
{
|
|
233
|
+
feature = Object.assign({}, feature, {type: 'Feature'})
|
|
234
|
+
const ids = this.__draw.add(feature)
|
|
235
|
+
this.__committedFeatures.set(ids[0], feature)
|
|
236
|
+
this.__uncommittedFeatureIds.delete(ids[0])
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
refreshGeometry(feature)
|
|
240
|
+
//======================
|
|
241
|
+
{
|
|
242
|
+
return this.__draw.get(feature.id) || null
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
//==============================================================================
|
package/src/controls/controls.js
CHANGED
|
@@ -526,6 +526,74 @@ export class NerveControl
|
|
|
526
526
|
|
|
527
527
|
//==============================================================================
|
|
528
528
|
|
|
529
|
+
export class AnnotatorControl
|
|
530
|
+
{
|
|
531
|
+
#enabled = false
|
|
532
|
+
|
|
533
|
+
constructor(flatmap)
|
|
534
|
+
{
|
|
535
|
+
this.__flatmap = flatmap
|
|
536
|
+
this.__map = null
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
getDefaultPosition()
|
|
540
|
+
//==================
|
|
541
|
+
{
|
|
542
|
+
return 'top-right'
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
onAdd(map)
|
|
546
|
+
//========
|
|
547
|
+
{
|
|
548
|
+
this.__map = map;
|
|
549
|
+
this.__container = document.createElement('div');
|
|
550
|
+
this.__container.className = 'maplibregl-ctrl';
|
|
551
|
+
|
|
552
|
+
this.__button = document.createElement('button');
|
|
553
|
+
this.__button.id = 'map-annotated-button';
|
|
554
|
+
this.__button.className = 'control-button text-button';
|
|
555
|
+
this.__button.setAttribute('type', 'button');
|
|
556
|
+
this.__button.setAttribute('aria-label', 'Draw on map for annotation');
|
|
557
|
+
this.__button.textContent = 'DRAW';
|
|
558
|
+
this.__button.title = 'Draw on map for annotation';
|
|
559
|
+
this.__container.appendChild(this.__button);
|
|
560
|
+
|
|
561
|
+
this.__container.addEventListener('click', this.onClick_.bind(this));
|
|
562
|
+
this.__setBackground();
|
|
563
|
+
return this.__container;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
__setBackground()
|
|
567
|
+
//===============
|
|
568
|
+
{
|
|
569
|
+
if (this.#enabled) {
|
|
570
|
+
this.__button.setAttribute('style', 'background: red');
|
|
571
|
+
} else {
|
|
572
|
+
this.__button.removeAttribute('style');
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
onRemove()
|
|
577
|
+
//========
|
|
578
|
+
{
|
|
579
|
+
this.__container.parentNode.removeChild(this.__container)
|
|
580
|
+
this.__map = null
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
onClick_(event)
|
|
584
|
+
//=============
|
|
585
|
+
{
|
|
586
|
+
if (event.target.id === 'map-annotated-button') {
|
|
587
|
+
this.#enabled = !this.#enabled
|
|
588
|
+
this.__setBackground()
|
|
589
|
+
this.__flatmap.showAnnotator(this.#enabled)
|
|
590
|
+
}
|
|
591
|
+
event.stopPropagation();
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
//==============================================================================
|
|
596
|
+
|
|
529
597
|
export class BackgroundControl
|
|
530
598
|
{
|
|
531
599
|
constructor(flatmap)
|
package/src/controls/minimap.js
CHANGED
|
@@ -151,13 +151,8 @@ export class MinimapControl
|
|
|
151
151
|
container: container,
|
|
152
152
|
style: map.getStyle(),
|
|
153
153
|
bounds: map.getBounds()
|
|
154
|
-
|
|
155
154
|
});
|
|
156
155
|
|
|
157
|
-
// Finish initialising once the map has loaded
|
|
158
|
-
|
|
159
|
-
this._miniMap.on('load', this.load_.bind(this));
|
|
160
|
-
|
|
161
156
|
return this._container;
|
|
162
157
|
}
|
|
163
158
|
|
|
@@ -169,8 +164,8 @@ export class MinimapControl
|
|
|
169
164
|
this._container = null;
|
|
170
165
|
}
|
|
171
166
|
|
|
172
|
-
|
|
173
|
-
|
|
167
|
+
initialise()
|
|
168
|
+
//==========
|
|
174
169
|
{
|
|
175
170
|
const opts = this._options;
|
|
176
171
|
const parentMap = this._map;
|
|
@@ -184,7 +179,7 @@ export class MinimapControl
|
|
|
184
179
|
];
|
|
185
180
|
interactions.forEach(i => miniMap[i].disable());
|
|
186
181
|
|
|
187
|
-
// Set background if specified (
|
|
182
|
+
// Set background if specified (default is the parent map's)
|
|
188
183
|
|
|
189
184
|
if (this._background !== null) {
|
|
190
185
|
miniMap.setPaintProperty('background', 'background-color', this._background);
|
package/src/controls/paths3d.js
CHANGED
|
@@ -22,6 +22,7 @@ export class Path3DControl
|
|
|
22
22
|
{
|
|
23
23
|
#button
|
|
24
24
|
#container
|
|
25
|
+
#enabled = false
|
|
25
26
|
#map = null
|
|
26
27
|
#flatmap
|
|
27
28
|
|
|
@@ -60,16 +61,29 @@ export class Path3DControl
|
|
|
60
61
|
this.#map = undefined
|
|
61
62
|
}
|
|
62
63
|
|
|
64
|
+
__setBackground()
|
|
65
|
+
//===============
|
|
66
|
+
{
|
|
67
|
+
if (this.#enabled) {
|
|
68
|
+
this.#button.setAttribute('style', 'background: red');
|
|
69
|
+
} else {
|
|
70
|
+
this.#button.removeAttribute('style');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
63
74
|
onClick(_event)
|
|
64
75
|
//=============
|
|
65
76
|
{
|
|
66
77
|
if (this.#button.classList.contains('control-active')) {
|
|
67
78
|
this.#flatmap.enable3dPaths(false)
|
|
68
79
|
this.#button.classList.remove('control-active')
|
|
80
|
+
this.#enabled = false
|
|
69
81
|
} else {
|
|
70
82
|
this.#flatmap.enable3dPaths(true)
|
|
71
83
|
this.#button.classList.add('control-active')
|
|
84
|
+
this.#enabled = true
|
|
72
85
|
}
|
|
86
|
+
this.__setBackground()
|
|
73
87
|
}
|
|
74
88
|
}
|
|
75
89
|
|
package/src/flatmap-viewer.js
CHANGED
|
@@ -37,8 +37,6 @@ import {MapServer, loadJSON} from './mapserver.js';
|
|
|
37
37
|
import {SearchIndex} from './search.js';
|
|
38
38
|
import {UserInteractions} from './interactions.js';
|
|
39
39
|
|
|
40
|
-
import {MinimapControl} from './controls/minimap.js';
|
|
41
|
-
import {NavigationControl} from './controls/controls.js';
|
|
42
40
|
import {APINATOMY_PATH_PREFIX} from './pathways';
|
|
43
41
|
|
|
44
42
|
import * as images from './images.js';
|
|
@@ -162,33 +160,16 @@ class FlatMap
|
|
|
162
160
|
|
|
163
161
|
this._map.setRenderWorldCopies(false);
|
|
164
162
|
|
|
165
|
-
// Do we want a fullscreen control?
|
|
166
|
-
|
|
167
|
-
if (mapDescription.options.fullscreenControl === true) {
|
|
168
|
-
this._map.addControl(new maplibregl.FullscreenControl(), 'top-right');
|
|
169
|
-
}
|
|
170
|
-
|
|
171
163
|
// Disable map rotation
|
|
172
164
|
|
|
173
165
|
//this._map.dragRotate.disable();
|
|
174
166
|
//this._map.touchZoomRotate.disableRotation();
|
|
175
167
|
|
|
176
|
-
// Add navigation controls if option set
|
|
177
|
-
|
|
178
|
-
if (mapDescription.options.navigationControl) {
|
|
179
|
-
const value = mapDescription.options.navigationControl;
|
|
180
|
-
const position = ((typeof value === 'string')
|
|
181
|
-
&& ['top-left', 'top-right', 'bottom-right', 'bottom-left'].includes(value))
|
|
182
|
-
? value : 'bottom-right';
|
|
183
|
-
this._map.addControl(new NavigationControl(this), position);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
168
|
// Finish initialisation when all sources have loaded
|
|
187
169
|
// and map has rendered
|
|
188
170
|
|
|
189
171
|
this._userInteractions = null;
|
|
190
172
|
this._initialState = null;
|
|
191
|
-
this._minimap = null;
|
|
192
173
|
|
|
193
174
|
this._map.on('idle', () => {
|
|
194
175
|
if (this._userInteractions === null) {
|
|
@@ -207,14 +188,9 @@ class FlatMap
|
|
|
207
188
|
this._userInteractions.setState(this._options.state);
|
|
208
189
|
}
|
|
209
190
|
this._initialState = this.getState();
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
if (this.options.minimap) {
|
|
214
|
-
this._minimap = new MinimapControl(this, this.options.minimap);
|
|
215
|
-
this._map.addControl(this._minimap);
|
|
216
|
-
}
|
|
217
|
-
|
|
191
|
+
if (this._userInteractions.minimap) {
|
|
192
|
+
this._userInteractions.minimap.initialise()
|
|
193
|
+
}
|
|
218
194
|
this._resolve(this);
|
|
219
195
|
}
|
|
220
196
|
});
|
|
@@ -224,13 +200,11 @@ class FlatMap
|
|
|
224
200
|
//============================
|
|
225
201
|
{
|
|
226
202
|
// Load any images required by the map
|
|
227
|
-
|
|
228
203
|
for (const image of this._options.images) {
|
|
229
204
|
await this.addImage(image.id, image.url, '', image.options);
|
|
230
205
|
}
|
|
231
206
|
|
|
232
207
|
// Layers have now loaded so finish setting up
|
|
233
|
-
|
|
234
208
|
this._userInteractions = new UserInteractions(this);
|
|
235
209
|
}
|
|
236
210
|
|
|
@@ -836,8 +810,8 @@ class FlatMap
|
|
|
836
810
|
|
|
837
811
|
this._map.setPaintProperty('background', 'background-color', colour);
|
|
838
812
|
|
|
839
|
-
if (this.
|
|
840
|
-
this.
|
|
813
|
+
if (this._userInteractions.minimap) {
|
|
814
|
+
this._userInteractions.minimap.setBackgroundColour(colour);
|
|
841
815
|
}
|
|
842
816
|
}
|
|
843
817
|
|
|
@@ -851,8 +825,8 @@ class FlatMap
|
|
|
851
825
|
{
|
|
852
826
|
this._map.setPaintProperty('background', 'background-opacity', opacity);
|
|
853
827
|
|
|
854
|
-
if (this.
|
|
855
|
-
this.
|
|
828
|
+
if (this._userInteractions.minimap) {
|
|
829
|
+
this._userInteractions.minimap.setBackgroundOpacity(opacity);
|
|
856
830
|
}
|
|
857
831
|
}
|
|
858
832
|
|
|
@@ -864,8 +838,8 @@ class FlatMap
|
|
|
864
838
|
showMinimap(show)
|
|
865
839
|
//===============
|
|
866
840
|
{
|
|
867
|
-
if (this.
|
|
868
|
-
this.
|
|
841
|
+
if (this._userInteractions.minimap) {
|
|
842
|
+
this._userInteractions.minimap.show(show);
|
|
869
843
|
}
|
|
870
844
|
|
|
871
845
|
}
|
|
@@ -1063,6 +1037,100 @@ class FlatMap
|
|
|
1063
1037
|
return data;
|
|
1064
1038
|
}
|
|
1065
1039
|
|
|
1040
|
+
/**
|
|
1041
|
+
* Show or hide a tool for drawing regions to annotate on the map.
|
|
1042
|
+
*
|
|
1043
|
+
* @param {boolean} [visible=true]
|
|
1044
|
+
*/
|
|
1045
|
+
showAnnotator(visible=true)
|
|
1046
|
+
//=========================
|
|
1047
|
+
{
|
|
1048
|
+
if (this._userInteractions !== null) {
|
|
1049
|
+
this._userInteractions.showAnnotator(visible)
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
/**
|
|
1054
|
+
* Generate an ``annotation`` callback event when a drawn annotation has been created
|
|
1055
|
+
* a modified.
|
|
1056
|
+
*
|
|
1057
|
+
* @param eventType {string} Either ``created``, ``updated`` or ``deleted``
|
|
1058
|
+
* @param feature {Object} A feature object with ``id``, ``type``, and ``geometry``
|
|
1059
|
+
* fields of a feature that has been created, updated or
|
|
1060
|
+
* deleted.
|
|
1061
|
+
*/
|
|
1062
|
+
annotationEvent(eventType, feature)
|
|
1063
|
+
//=================================
|
|
1064
|
+
{
|
|
1065
|
+
this.callback('annotation', {
|
|
1066
|
+
type: eventType,
|
|
1067
|
+
feature: feature
|
|
1068
|
+
});
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
/**
|
|
1072
|
+
* Mark a drawn/changed annotation as having been accepted by the user.
|
|
1073
|
+
*
|
|
1074
|
+
* @param event {Object} The object as received in an annotation callback
|
|
1075
|
+
* @param event.type {string} Either ``created``, ``updated`` or ``deleted``
|
|
1076
|
+
* @param event.feature {Object} A feature object.
|
|
1077
|
+
*/
|
|
1078
|
+
commitAnnotationEvent(event)
|
|
1079
|
+
//==========================
|
|
1080
|
+
{
|
|
1081
|
+
if (this._userInteractions) {
|
|
1082
|
+
this._userInteractions.commitAnnotationEvent(event)
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
/**
|
|
1087
|
+
* Mark a drawn/changed annotation as having been rejected by the user.
|
|
1088
|
+
*
|
|
1089
|
+
* @param event {Object} The object as received in an annotation callback
|
|
1090
|
+
* @param event.type {string} Either ``created``, ``updated`` or ``deleted``
|
|
1091
|
+
* @param event.feature {Object} A feature object.
|
|
1092
|
+
*/
|
|
1093
|
+
rollbackAnnotationEvent(event)
|
|
1094
|
+
//============================
|
|
1095
|
+
{
|
|
1096
|
+
if (this._userInteractions) {
|
|
1097
|
+
this._userInteractions.rollbackAnnotationEvent(event)
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
/**
|
|
1102
|
+
* Add a drawn feature to the annotation drawing tool.
|
|
1103
|
+
*
|
|
1104
|
+
* @param feature {Object} The feature to add
|
|
1105
|
+
* @param feature.id {string} The feature's id
|
|
1106
|
+
* @param feature.geometry {Object} The feature's geometry as GeoJSON
|
|
1107
|
+
*/
|
|
1108
|
+
addAnnotationFeature(feature)
|
|
1109
|
+
//===========================
|
|
1110
|
+
{
|
|
1111
|
+
if (this._userInteractions) {
|
|
1112
|
+
this._userInteractions.addAnnotationFeature(feature)
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
/**
|
|
1117
|
+
* Return the feature as it is currently drawn. This is so
|
|
1118
|
+
* the correct geometry can be saved with a feature should
|
|
1119
|
+
* a user make changes before submitting dialog provided
|
|
1120
|
+
* by an external annotator.
|
|
1121
|
+
*
|
|
1122
|
+
* @param feature {Object} The drawn feature to refresh.
|
|
1123
|
+
* @returns {Object|null} The feature with currently geometry or ``null``
|
|
1124
|
+
* if the feature has been deleted.
|
|
1125
|
+
*/
|
|
1126
|
+
refreshAnnotationFeatureGeometry(feature)
|
|
1127
|
+
//=======================================
|
|
1128
|
+
{
|
|
1129
|
+
if (this._userInteractions) {
|
|
1130
|
+
this._userInteractions.refreshAnnotationFeatureGeometry(feature)
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1066
1134
|
/**
|
|
1067
1135
|
* Generate a callback as a result of some event with a flatmap feature.
|
|
1068
1136
|
*
|