@versatiles/svelte 2.0.1 → 2.1.0
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/components/BBoxMap/BBoxMap.svelte +23 -12
- package/dist/components/BBoxMap/lib/bbox.d.ts +1 -1
- package/dist/components/BBoxMap/lib/bbox.js +19 -17
- package/dist/components/BasicMap/BasicMap.svelte +22 -9
- package/dist/components/BasicMap/BasicMap.svelte.d.ts +2 -1
- package/dist/components/MapEditor/MapEditor.svelte +51 -20
- package/dist/components/MapEditor/components/Dialog.svelte +92 -0
- package/dist/components/MapEditor/components/Dialog.svelte.d.ts +17 -0
- package/dist/components/MapEditor/components/DialogFile.svelte +112 -0
- package/dist/components/MapEditor/components/DialogFile.svelte.d.ts +6 -0
- package/dist/components/MapEditor/components/DialogShare.svelte +216 -0
- package/dist/components/MapEditor/components/DialogShare.svelte.d.ts +10 -0
- package/dist/components/MapEditor/components/Editor.svelte +6 -14
- package/dist/components/MapEditor/components/EditorFill.svelte +3 -3
- package/dist/components/MapEditor/components/EditorStroke.svelte +3 -3
- package/dist/components/MapEditor/components/EditorSymbol.svelte +9 -9
- package/dist/components/MapEditor/components/InputRow.svelte +2 -3
- package/dist/components/MapEditor/components/PanelFile.svelte +73 -0
- package/dist/components/MapEditor/components/PanelFile.svelte.d.ts +7 -0
- package/dist/components/MapEditor/components/PanelSymbolSelector.svelte +82 -0
- package/dist/components/MapEditor/components/PanelSymbolSelector.svelte.d.ts +8 -0
- package/dist/components/MapEditor/components/Sidebar.svelte +51 -98
- package/dist/components/MapEditor/components/Sidebar.svelte.d.ts +3 -3
- package/dist/components/MapEditor/components/SidebarPanel.svelte +13 -5
- package/dist/components/MapEditor/lib/element/abstract.d.ts +8 -4
- package/dist/components/MapEditor/lib/element/abstract.js +10 -1
- package/dist/components/MapEditor/lib/element/abstract_path.d.ts +3 -2
- package/dist/components/MapEditor/lib/element/abstract_path.js +6 -3
- package/dist/components/MapEditor/lib/element/circle.d.ts +25 -0
- package/dist/components/MapEditor/lib/element/circle.js +118 -0
- package/dist/components/MapEditor/lib/element/line.d.ts +2 -2
- package/dist/components/MapEditor/lib/element/line.js +1 -1
- package/dist/components/MapEditor/lib/element/marker.d.ts +4 -3
- package/dist/components/MapEditor/lib/element/marker.js +2 -2
- package/dist/components/MapEditor/lib/element/polygon.d.ts +2 -2
- package/dist/components/MapEditor/lib/element/polygon.js +2 -2
- package/dist/components/MapEditor/lib/element/types.d.ts +2 -3
- package/dist/components/MapEditor/lib/geometry_manager.d.ts +12 -29
- package/dist/components/MapEditor/lib/geometry_manager.js +44 -160
- package/dist/components/MapEditor/lib/geometry_manager_interactive.d.ts +33 -0
- package/dist/components/MapEditor/lib/geometry_manager_interactive.js +102 -0
- package/dist/components/MapEditor/lib/map_layer/abstract.d.ts +2 -1
- package/dist/components/MapEditor/lib/map_layer/abstract.js +25 -22
- package/dist/components/MapEditor/lib/map_layer/fill.js +2 -4
- package/dist/components/MapEditor/lib/map_layer/line.js +1 -1
- package/dist/components/MapEditor/lib/map_layer/symbol.js +1 -1
- package/dist/components/MapEditor/lib/selection.d.ts +11 -0
- package/dist/components/MapEditor/lib/selection.js +70 -0
- package/dist/components/MapEditor/lib/state/constants.js +5 -6
- package/dist/components/MapEditor/lib/state/history.d.ts +14 -0
- package/dist/components/MapEditor/lib/state/history.js +53 -0
- package/dist/components/MapEditor/lib/state/manager.d.ts +7 -10
- package/dist/components/MapEditor/lib/state/manager.js +19 -54
- package/dist/components/MapEditor/lib/state/reader.d.ts +6 -4
- package/dist/components/MapEditor/lib/state/reader.js +70 -18
- package/dist/components/MapEditor/lib/state/types.d.ts +19 -2
- package/dist/components/MapEditor/lib/state/utils.d.ts +2 -0
- package/dist/components/MapEditor/lib/state/utils.js +12 -0
- package/dist/components/MapEditor/lib/state/writer.d.ts +6 -4
- package/dist/components/MapEditor/lib/state/writer.js +59 -19
- package/dist/components/MapEditor/lib/symbols.d.ts +1 -1
- package/dist/components/MapEditor/lib/symbols.js +47 -28
- package/dist/components/MapEditor/lib/utils/event_handler.d.ts +10 -0
- package/dist/components/MapEditor/lib/utils/event_handler.js +39 -0
- package/dist/components/MapEditor/lib/utils/geometry.d.ts +12 -0
- package/dist/components/MapEditor/lib/utils/geometry.js +87 -0
- package/dist/components/MapEditor/lib/utils/types.d.ts +2 -0
- package/dist/components/MapEditor/lib/utils/types.js +1 -0
- package/dist/components/MapEditor/style/button.scss +115 -0
- package/dist/components/MapEditor/style/index.scss +3 -0
- package/dist/components/MapEditor/style/layout.scss +20 -0
- package/dist/components/MapEditor/style/other.scss +10 -0
- package/dist/utils/location.d.ts +1 -0
- package/dist/utils/location.js +181 -0
- package/dist/utils/map_style.d.ts +2 -2
- package/dist/utils/map_style.js +2 -2
- package/package.json +29 -29
- package/dist/components/MapEditor/components/SymbolSelector.svelte +0 -110
- package/dist/components/MapEditor/components/SymbolSelector.svelte.d.ts +0 -8
- package/dist/components/MapEditor/lib/utils.d.ts +0 -6
- package/dist/components/MapEditor/lib/utils.js +0 -23
- /package/dist/components/MapEditor/lib/{geocoder.d.ts → utils/geocoder.d.ts} +0 -0
- /package/dist/components/MapEditor/lib/{geocoder.js → utils/geocoder.js} +0 -0
@@ -1,38 +1,21 @@
|
|
1
|
-
import { type Writable } from 'svelte/store';
|
2
1
|
import type { AbstractElement } from './element/abstract.js';
|
3
|
-
import {
|
4
|
-
import {
|
5
|
-
import {
|
6
|
-
import { Cursor } from './cursor.js';
|
7
|
-
import { SymbolLibrary } from './symbols.js';
|
8
|
-
import { StateManager } from './state/manager.js';
|
2
|
+
import type { GeometryManagerInteractive } from './geometry_manager_interactive.js';
|
3
|
+
import type { SelectionHandler } from './selection.js';
|
4
|
+
import type { StateManager } from './state/manager.js';
|
9
5
|
import type { StateRoot } from './state/types.js';
|
10
|
-
|
11
|
-
map?: {
|
12
|
-
center: [number, number];
|
13
|
-
zoom: number;
|
14
|
-
};
|
15
|
-
};
|
6
|
+
import { type Writable } from 'svelte/store';
|
16
7
|
export declare class GeometryManager {
|
17
8
|
readonly elements: Writable<AbstractElement[]>;
|
18
9
|
readonly map: maplibregl.Map;
|
19
|
-
readonly selectedElement: Writable<AbstractElement | undefined>;
|
20
10
|
readonly canvas: HTMLElement;
|
21
|
-
readonly
|
22
|
-
readonly
|
23
|
-
readonly state: StateManager;
|
24
|
-
private readonly selectionNodes;
|
11
|
+
readonly state: StateManager | null;
|
12
|
+
readonly selection: SelectionHandler | null;
|
25
13
|
constructor(map: maplibregl.Map);
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
setState(state: StateRoot): void;
|
30
|
-
getElement(index: number): AbstractElement;
|
31
|
-
addNewMarker(): MarkerElement;
|
32
|
-
addNewLine(): LineElement;
|
33
|
-
addNewPolygon(): PolygonElement;
|
34
|
-
private appendElement;
|
14
|
+
isInteractive(): this is GeometryManagerInteractive;
|
15
|
+
clear(): void;
|
16
|
+
protected appendElement(element: AbstractElement): void;
|
35
17
|
removeElement(element: AbstractElement): void;
|
36
|
-
|
37
|
-
|
18
|
+
loadState(state: StateRoot): Promise<void>;
|
19
|
+
setState(state: StateRoot): Promise<void>;
|
20
|
+
getElement(index: number): AbstractElement;
|
38
21
|
}
|
@@ -1,31 +1,26 @@
|
|
1
1
|
import { get, writable } from 'svelte/store';
|
2
|
-
import {
|
2
|
+
import { getMapStyle } from '../../../utils/map_style.js';
|
3
|
+
import { CircleElement } from './element/circle.js';
|
3
4
|
import { LineElement } from './element/line.js';
|
5
|
+
import { MarkerElement } from './element/marker.js';
|
4
6
|
import { PolygonElement } from './element/polygon.js';
|
5
|
-
import { Cursor } from './cursor.js';
|
6
|
-
import { SymbolLibrary } from './symbols.js';
|
7
|
-
import { StateManager } from './state/manager.js';
|
8
7
|
export class GeometryManager {
|
9
8
|
elements;
|
10
9
|
map;
|
11
|
-
selectedElement = writable(undefined);
|
12
10
|
canvas;
|
13
|
-
|
14
|
-
|
15
|
-
state;
|
16
|
-
selectionNodes;
|
11
|
+
state = null;
|
12
|
+
selection = null;
|
17
13
|
constructor(map) {
|
18
14
|
this.elements = writable([]);
|
19
15
|
this.map = map;
|
20
16
|
this.canvas = this.map.getCanvasContainer();
|
21
|
-
|
22
|
-
|
23
|
-
|
17
|
+
const style = getMapStyle({ darkMode: false });
|
18
|
+
style.transition = { duration: 0, delay: 0 };
|
19
|
+
style.sources.selection_nodes = {
|
24
20
|
type: 'geojson',
|
25
21
|
data: { type: 'FeatureCollection', features: [] }
|
26
|
-
}
|
27
|
-
|
28
|
-
map.addLayer({
|
22
|
+
};
|
23
|
+
style.layers.push({
|
29
24
|
id: 'selection_nodes',
|
30
25
|
source: 'selection_nodes',
|
31
26
|
type: 'circle',
|
@@ -39,91 +34,46 @@ export class GeometryManager {
|
|
39
34
|
'circle-stroke-width': 1
|
40
35
|
}
|
41
36
|
});
|
42
|
-
map.
|
43
|
-
const element = get(this.selectedElement);
|
44
|
-
if (element == undefined)
|
45
|
-
return;
|
46
|
-
const feature = map.queryRenderedFeatures(e.point, { layers: ['selection_nodes'] })[0];
|
47
|
-
const selectedNode = element.getSelectionNodeUpdater(feature.properties);
|
48
|
-
if (selectedNode == undefined)
|
49
|
-
return;
|
50
|
-
// @ts-expect-error ensure that the event is ignored by other layers
|
51
|
-
e.ignore = true;
|
52
|
-
e.preventDefault();
|
53
|
-
if (e.originalEvent.shiftKey) {
|
54
|
-
selectedNode.delete();
|
55
|
-
this.drawSelectionNodes();
|
56
|
-
}
|
57
|
-
else {
|
58
|
-
const onMove = (e) => {
|
59
|
-
e.preventDefault();
|
60
|
-
selectedNode.update(e.lngLat.lng, e.lngLat.lat);
|
61
|
-
this.drawSelectionNodes();
|
62
|
-
};
|
63
|
-
map.on('mousemove', onMove);
|
64
|
-
map.once('mouseup', () => {
|
65
|
-
map.off('mousemove', onMove);
|
66
|
-
this.state.log();
|
67
|
-
});
|
68
|
-
}
|
69
|
-
});
|
70
|
-
map.on('mouseenter', 'selection_nodes', () => {
|
71
|
-
this.cursor.togglePrecise('selection_nodes');
|
72
|
-
});
|
73
|
-
map.on('mouseleave', 'selection_nodes', () => {
|
74
|
-
this.cursor.togglePrecise('selection_nodes', false);
|
75
|
-
});
|
76
|
-
map.on('click', (e) => {
|
77
|
-
if (!e.originalEvent.shiftKey)
|
78
|
-
this.selectElement(undefined);
|
79
|
-
e.preventDefault();
|
80
|
-
});
|
81
|
-
this.state = new StateManager(this);
|
37
|
+
map.setStyle(style);
|
82
38
|
}
|
83
|
-
|
84
|
-
|
85
|
-
return;
|
86
|
-
const elements = get(this.elements);
|
87
|
-
elements.forEach((e) => e.select(e == element));
|
88
|
-
this.selectedElement.set(element);
|
89
|
-
this.drawSelectionNodes();
|
39
|
+
isInteractive() {
|
40
|
+
return false;
|
90
41
|
}
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
features: nodes.map((n) => ({
|
96
|
-
type: 'Feature',
|
97
|
-
properties: { index: n.index, opacity: n.transparent ? 0.3 : 1 },
|
98
|
-
geometry: { type: 'Point', coordinates: n.coordinates }
|
99
|
-
}))
|
42
|
+
clear() {
|
43
|
+
this.elements.update((elements) => {
|
44
|
+
elements.forEach((e) => e.destroy());
|
45
|
+
return [];
|
100
46
|
});
|
101
47
|
}
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
zoom: this.map.getZoom()
|
108
|
-
},
|
109
|
-
elements: get(this.elements).map((element) => element.getState())
|
110
|
-
};
|
48
|
+
appendElement(element) {
|
49
|
+
this.elements.update((elements) => [...elements, element]);
|
50
|
+
}
|
51
|
+
removeElement(element) {
|
52
|
+
this.elements.update((elements) => elements.filter((e) => e !== element));
|
111
53
|
}
|
112
|
-
|
54
|
+
async loadState(state) {
|
113
55
|
if (!state)
|
114
56
|
return;
|
115
|
-
this.
|
116
|
-
this.
|
117
|
-
|
118
|
-
|
119
|
-
|
57
|
+
this.clear();
|
58
|
+
this.setState(state);
|
59
|
+
this.state?.history.reset(state);
|
60
|
+
}
|
61
|
+
async setState(state) {
|
62
|
+
if (!state)
|
63
|
+
return;
|
64
|
+
this.clear();
|
120
65
|
if (state.map) {
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
66
|
+
const { center, radius } = state.map;
|
67
|
+
const dy = (radius * 360) / 40074000;
|
68
|
+
const dx = dy / Math.cos((center[1] * Math.PI) / 180);
|
69
|
+
const bounds = [
|
70
|
+
[center[0] - dx, center[1] - dy],
|
71
|
+
[center[0] + dx, center[1] + dy]
|
72
|
+
];
|
73
|
+
this.map.fitBounds(bounds, { animate: false });
|
74
|
+
}
|
75
|
+
if (!this.map.isStyleLoaded()) {
|
76
|
+
await new Promise((r) => this.map.once('styledata', r));
|
127
77
|
}
|
128
78
|
if (state.elements) {
|
129
79
|
const elements = state.elements.map((element) => {
|
@@ -134,6 +84,8 @@ export class GeometryManager {
|
|
134
84
|
return LineElement.fromState(this, element);
|
135
85
|
case 'polygon':
|
136
86
|
return PolygonElement.fromState(this, element);
|
87
|
+
case 'circle':
|
88
|
+
return CircleElement.fromState(this, element);
|
137
89
|
default:
|
138
90
|
throw new Error('Unknown element type');
|
139
91
|
}
|
@@ -144,72 +96,4 @@ export class GeometryManager {
|
|
144
96
|
getElement(index) {
|
145
97
|
return get(this.elements)[index];
|
146
98
|
}
|
147
|
-
addNewMarker() {
|
148
|
-
const element = new MarkerElement(this);
|
149
|
-
this.appendElement(element);
|
150
|
-
this.selectElement(element);
|
151
|
-
return element;
|
152
|
-
}
|
153
|
-
addNewLine() {
|
154
|
-
const element = new LineElement(this);
|
155
|
-
this.appendElement(element);
|
156
|
-
this.selectElement(element);
|
157
|
-
return element;
|
158
|
-
}
|
159
|
-
addNewPolygon() {
|
160
|
-
const element = new PolygonElement(this);
|
161
|
-
this.appendElement(element);
|
162
|
-
this.selectElement(element);
|
163
|
-
return element;
|
164
|
-
}
|
165
|
-
appendElement(element) {
|
166
|
-
this.elements.update((elements) => [...elements, element]);
|
167
|
-
}
|
168
|
-
removeElement(element) {
|
169
|
-
if (get(this.selectedElement) === element)
|
170
|
-
this.selectElement(undefined);
|
171
|
-
this.elements.update((elements) => elements.filter((e) => e !== element));
|
172
|
-
}
|
173
|
-
getGeoJSON() {
|
174
|
-
const center = this.map.getCenter();
|
175
|
-
return {
|
176
|
-
type: 'FeatureCollection',
|
177
|
-
map: {
|
178
|
-
center: [center.lng, center.lat],
|
179
|
-
zoom: this.map.getZoom()
|
180
|
-
},
|
181
|
-
features: get(this.elements).map((element) => element.getFeature(true))
|
182
|
-
};
|
183
|
-
}
|
184
|
-
addGeoJSON(geojson) {
|
185
|
-
if ('map' in geojson && geojson.map) {
|
186
|
-
const { map } = geojson;
|
187
|
-
if (typeof map.zoom === 'number') {
|
188
|
-
this.map.setZoom(map.zoom);
|
189
|
-
}
|
190
|
-
if (Array.isArray(map.center)) {
|
191
|
-
const [lng, lat] = map.center;
|
192
|
-
if (typeof lng === 'number' && typeof lat === 'number') {
|
193
|
-
this.map.setCenter({ lng, lat });
|
194
|
-
}
|
195
|
-
}
|
196
|
-
}
|
197
|
-
for (const feature of geojson.features) {
|
198
|
-
let element;
|
199
|
-
switch (feature.geometry.type) {
|
200
|
-
case 'Point':
|
201
|
-
element = MarkerElement.fromGeoJSON(this, feature);
|
202
|
-
break;
|
203
|
-
case 'LineString':
|
204
|
-
element = LineElement.fromGeoJSON(this, feature);
|
205
|
-
break;
|
206
|
-
case 'Polygon':
|
207
|
-
element = PolygonElement.fromGeoJSON(this, feature);
|
208
|
-
break;
|
209
|
-
default:
|
210
|
-
throw new Error(`Unknown geometry type "${feature.geometry.type}"`);
|
211
|
-
}
|
212
|
-
this.appendElement(element);
|
213
|
-
}
|
214
|
-
}
|
215
99
|
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import type { AbstractElement } from './element/abstract.js';
|
2
|
+
import { CircleElement } from './element/circle.js';
|
3
|
+
import { LineElement } from './element/line.js';
|
4
|
+
import { MarkerElement } from './element/marker.js';
|
5
|
+
import { PolygonElement } from './element/polygon.js';
|
6
|
+
import { GeometryManager } from './geometry_manager.js';
|
7
|
+
import { SelectionHandler } from './selection.js';
|
8
|
+
import { Cursor } from './cursor.js';
|
9
|
+
import { StateManager } from './state/manager.js';
|
10
|
+
import type { StateRoot } from './state/types.js';
|
11
|
+
export type ExtendedGeoJSON = GeoJSON.FeatureCollection & {
|
12
|
+
map?: {
|
13
|
+
center: [number, number];
|
14
|
+
zoom: number;
|
15
|
+
};
|
16
|
+
};
|
17
|
+
export declare class GeometryManagerInteractive extends GeometryManager {
|
18
|
+
readonly selection: SelectionHandler;
|
19
|
+
readonly cursor: Cursor;
|
20
|
+
readonly state: StateManager;
|
21
|
+
constructor(map: maplibregl.Map);
|
22
|
+
clear(): void;
|
23
|
+
isInteractive(): this is GeometryManagerInteractive;
|
24
|
+
removeElement(element: AbstractElement): void;
|
25
|
+
addNewElement(type: 'marker'): MarkerElement;
|
26
|
+
addNewElement(type: 'line'): LineElement;
|
27
|
+
addNewElement(type: 'polygon'): PolygonElement;
|
28
|
+
addNewElement(type: 'circle'): CircleElement;
|
29
|
+
addNewElement(type: 'marker' | 'line' | 'polygon' | 'circle'): AbstractElement;
|
30
|
+
getGeoJSON(): GeoJSON.FeatureCollection;
|
31
|
+
getState(): StateRoot;
|
32
|
+
addGeoJSON(geojson: ExtendedGeoJSON): void;
|
33
|
+
}
|
@@ -0,0 +1,102 @@
|
|
1
|
+
import { get } from 'svelte/store';
|
2
|
+
import { CircleElement } from './element/circle.js';
|
3
|
+
import { LineElement } from './element/line.js';
|
4
|
+
import { MarkerElement } from './element/marker.js';
|
5
|
+
import { PolygonElement } from './element/polygon.js';
|
6
|
+
import { GeometryManager } from './geometry_manager.js';
|
7
|
+
import { SelectionHandler } from './selection.js';
|
8
|
+
import { flatten } from './utils/geometry.js';
|
9
|
+
import { Cursor } from './cursor.js';
|
10
|
+
import { StateManager } from './state/manager.js';
|
11
|
+
export class GeometryManagerInteractive extends GeometryManager {
|
12
|
+
selection;
|
13
|
+
cursor;
|
14
|
+
state;
|
15
|
+
constructor(map) {
|
16
|
+
super(map);
|
17
|
+
this.cursor = new Cursor(map.getCanvasContainer());
|
18
|
+
this.selection = new SelectionHandler(this);
|
19
|
+
this.state = new StateManager(this);
|
20
|
+
}
|
21
|
+
clear() {
|
22
|
+
this.selection.selectElement();
|
23
|
+
super.clear();
|
24
|
+
}
|
25
|
+
isInteractive() {
|
26
|
+
return true;
|
27
|
+
}
|
28
|
+
removeElement(element) {
|
29
|
+
this.selection.selectElement();
|
30
|
+
super.removeElement(element);
|
31
|
+
}
|
32
|
+
addNewElement(type) {
|
33
|
+
const AbstractClass = {
|
34
|
+
marker: MarkerElement,
|
35
|
+
line: LineElement,
|
36
|
+
polygon: PolygonElement,
|
37
|
+
circle: CircleElement
|
38
|
+
}[type];
|
39
|
+
const element = new AbstractClass(this);
|
40
|
+
this.appendElement(element);
|
41
|
+
this.selection.selectElement(element);
|
42
|
+
return element;
|
43
|
+
}
|
44
|
+
getGeoJSON() {
|
45
|
+
const center = this.map.getCenter();
|
46
|
+
return {
|
47
|
+
type: 'FeatureCollection',
|
48
|
+
map: {
|
49
|
+
center: [center.lng, center.lat],
|
50
|
+
zoom: this.map.getZoom()
|
51
|
+
},
|
52
|
+
features: get(this.elements).map((element) => element.getGeoJSON())
|
53
|
+
};
|
54
|
+
}
|
55
|
+
getState() {
|
56
|
+
const center = this.map.getCenter();
|
57
|
+
const bounds = this.map.getBounds();
|
58
|
+
const radiusDegrees = Math.min(bounds.getNorth() - bounds.getSouth(), (bounds.getEast() - bounds.getWest()) * Math.cos((center.lat * Math.PI) / 180)) / 2;
|
59
|
+
const radius = 40074000 * (radiusDegrees / 360);
|
60
|
+
return {
|
61
|
+
map: {
|
62
|
+
center: [center.lng, center.lat],
|
63
|
+
radius
|
64
|
+
},
|
65
|
+
elements: get(this.elements).map((element) => element.getState())
|
66
|
+
};
|
67
|
+
}
|
68
|
+
addGeoJSON(geojson) {
|
69
|
+
if ('map' in geojson && geojson.map) {
|
70
|
+
const { map } = geojson;
|
71
|
+
if (typeof map.zoom === 'number') {
|
72
|
+
this.map.setZoom(map.zoom);
|
73
|
+
}
|
74
|
+
if (Array.isArray(map.center)) {
|
75
|
+
const [lng, lat] = map.center;
|
76
|
+
if (typeof lng === 'number' && typeof lat === 'number') {
|
77
|
+
this.map.setCenter({ lng, lat });
|
78
|
+
}
|
79
|
+
}
|
80
|
+
}
|
81
|
+
for (const feature of flatten(geojson.features)) {
|
82
|
+
let element;
|
83
|
+
const p = feature.properties;
|
84
|
+
switch (feature.geometry.type) {
|
85
|
+
case 'Point':
|
86
|
+
if (p && p.subType == 'Circle' && p.radius != null) {
|
87
|
+
element = CircleElement.fromGeoJSON(this, feature);
|
88
|
+
break;
|
89
|
+
}
|
90
|
+
element = MarkerElement.fromGeoJSON(this, feature);
|
91
|
+
break;
|
92
|
+
case 'LineString':
|
93
|
+
element = LineElement.fromGeoJSON(this, feature);
|
94
|
+
break;
|
95
|
+
case 'Polygon':
|
96
|
+
element = PolygonElement.fromGeoJSON(this, feature);
|
97
|
+
break;
|
98
|
+
}
|
99
|
+
this.appendElement(element);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
}
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import type { LayerFill, LayerLine, LayerSymbol } from './types.js';
|
2
2
|
import type { GeometryManager } from '../geometry_manager.js';
|
3
3
|
import type { StateStyle } from '../state/types.js';
|
4
|
+
import type { GeometryManagerInteractive } from '../geometry_manager_interactive.js';
|
4
5
|
type LayerSpec = LayerFill | LayerLine | LayerSymbol;
|
5
6
|
type Events = 'click' | 'mousedown' | 'mousemove' | 'mouseup';
|
6
7
|
type MouseEventHandler = (event: maplibregl.MapMouseEvent) => void;
|
@@ -8,7 +9,7 @@ export declare abstract class MapLayer<T extends LayerSpec> {
|
|
8
9
|
private layout;
|
9
10
|
private paint;
|
10
11
|
protected readonly id: string;
|
11
|
-
readonly manager: GeometryManager;
|
12
|
+
readonly manager: GeometryManager | GeometryManagerInteractive;
|
12
13
|
protected readonly map: maplibregl.Map;
|
13
14
|
eventHandlers: Map<Events, MouseEventHandler[]>;
|
14
15
|
isSelected: boolean;
|
@@ -45,28 +45,31 @@ export class MapLayer {
|
|
45
45
|
handlers.forEach((handler) => handler(e));
|
46
46
|
}
|
47
47
|
addEvents() {
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
this.
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
48
|
+
const manager = this.manager;
|
49
|
+
if (manager.isInteractive()) {
|
50
|
+
this.map.on('mouseenter', this.id, () => {
|
51
|
+
if (this.isSelected)
|
52
|
+
manager.cursor.toggleGrab(this.id);
|
53
|
+
manager.cursor.toggleHover(this.id);
|
54
|
+
});
|
55
|
+
this.map.on('mouseleave', this.id, () => {
|
56
|
+
if (this.isSelected)
|
57
|
+
manager.cursor.toggleGrab(this.id, false);
|
58
|
+
manager.cursor.toggleHover(this.id, false);
|
59
|
+
});
|
60
|
+
this.map.on('click', this.id, (e) => {
|
61
|
+
this.dispatchEvent('click', e);
|
62
|
+
if (this.isSelected)
|
63
|
+
manager.cursor.toggleGrab(this.id);
|
64
|
+
manager.cursor.toggleHover(this.id);
|
65
|
+
e.preventDefault();
|
66
|
+
});
|
67
|
+
this.map.on('mousedown', this.id, (e) => {
|
68
|
+
if (manager.cursor.isPrecise())
|
69
|
+
return;
|
70
|
+
this.dispatchEvent('mousedown', e);
|
71
|
+
});
|
72
|
+
}
|
70
73
|
this.map.on('mouseup', this.id, (e) => this.dispatchEvent('mouseup', e));
|
71
74
|
this.map.on('mousemove', this.id, (e) => this.dispatchEvent('mousemove', e));
|
72
75
|
}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { get, writable } from 'svelte/store';
|
2
2
|
import { MapLayer } from './abstract.js';
|
3
3
|
import { Color } from '@versatiles/style';
|
4
|
-
import { removeDefaultFields } from '../utils.js';
|
4
|
+
import { removeDefaultFields } from '../state/utils.js';
|
5
5
|
const size = 32;
|
6
6
|
export const fillPatterns = new Map([
|
7
7
|
[0, { name: 'solid', fill: undefined }],
|
@@ -86,9 +86,7 @@ export class MapLayerFill extends MapLayer {
|
|
86
86
|
if (properties['fill-opacity'])
|
87
87
|
this.opacity.set(properties['fill-opacity']);
|
88
88
|
if (properties['fill-pattern']) {
|
89
|
-
const pattern = fillPatterns
|
90
|
-
.entries()
|
91
|
-
.find(([, { name }]) => name === properties['fill-pattern']);
|
89
|
+
const pattern = fillPatterns.entries().find(([, { name }]) => name === properties['fill-pattern']);
|
92
90
|
if (pattern)
|
93
91
|
this.pattern.set(pattern[0]);
|
94
92
|
}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { derived, get, writable } from 'svelte/store';
|
2
2
|
import { MapLayer } from './abstract.js';
|
3
3
|
import { Color } from '@versatiles/style';
|
4
|
-
import { removeDefaultFields } from '../utils.js';
|
4
|
+
import { removeDefaultFields } from '../state/utils.js';
|
5
5
|
export const dashArrays = new Map([
|
6
6
|
[0, { name: 'solid', array: [100] }],
|
7
7
|
[1, { name: 'dashed', array: [2, 4] }],
|
@@ -2,7 +2,7 @@ import { derived, get, writable } from 'svelte/store';
|
|
2
2
|
import { MapLayer } from './abstract.js';
|
3
3
|
import { Color } from '@versatiles/style';
|
4
4
|
import { getSymbol, getSymbolIndexByName } from '../symbols.js';
|
5
|
-
import { removeDefaultFields } from '../utils.js';
|
5
|
+
import { removeDefaultFields } from '../state/utils.js';
|
6
6
|
export const labelPositions = [
|
7
7
|
{ index: 0, name: 'auto' },
|
8
8
|
{ index: 1, name: 'right', anchor: 'left' },
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { type Writable } from 'svelte/store';
|
2
|
+
import type { AbstractElement } from './element/abstract.js';
|
3
|
+
import type { GeometryManagerInteractive } from './geometry_manager_interactive.js';
|
4
|
+
export declare class SelectionHandler {
|
5
|
+
readonly selectedElement: Writable<AbstractElement | undefined>;
|
6
|
+
private selectionNodes;
|
7
|
+
private manager;
|
8
|
+
constructor(manager: GeometryManagerInteractive);
|
9
|
+
selectElement(element?: AbstractElement): void;
|
10
|
+
updateSelectionNodes(): void;
|
11
|
+
}
|
@@ -0,0 +1,70 @@
|
|
1
|
+
import { get, writable } from 'svelte/store';
|
2
|
+
export class SelectionHandler {
|
3
|
+
selectedElement = writable(undefined);
|
4
|
+
selectionNodes;
|
5
|
+
manager;
|
6
|
+
constructor(manager) {
|
7
|
+
this.manager = manager;
|
8
|
+
const map = this.manager.map;
|
9
|
+
map.on('mousedown', 'selection_nodes', (e) => {
|
10
|
+
const element = get(this.selectedElement);
|
11
|
+
if (element == null)
|
12
|
+
return;
|
13
|
+
const feature = map.queryRenderedFeatures(e.point, { layers: ['selection_nodes'] })[0];
|
14
|
+
const selectedNode = element.getSelectionNodeUpdater(feature.properties);
|
15
|
+
if (selectedNode == null)
|
16
|
+
return;
|
17
|
+
// @ts-expect-error ensure that the event is ignored by other layers
|
18
|
+
e.ignore = true;
|
19
|
+
e.preventDefault();
|
20
|
+
if (e.originalEvent.shiftKey) {
|
21
|
+
selectedNode.delete();
|
22
|
+
this.updateSelectionNodes();
|
23
|
+
}
|
24
|
+
else {
|
25
|
+
const onMove = (e) => {
|
26
|
+
e.preventDefault();
|
27
|
+
selectedNode.update(e.lngLat.lng, e.lngLat.lat);
|
28
|
+
this.updateSelectionNodes();
|
29
|
+
};
|
30
|
+
map.on('mousemove', onMove);
|
31
|
+
map.once('mouseup', () => {
|
32
|
+
map.off('mousemove', onMove);
|
33
|
+
this.manager.state.log();
|
34
|
+
});
|
35
|
+
}
|
36
|
+
});
|
37
|
+
map.on('mouseenter', 'selection_nodes', () => {
|
38
|
+
this.manager.cursor.togglePrecise('selection_nodes');
|
39
|
+
});
|
40
|
+
map.on('mouseleave', 'selection_nodes', () => {
|
41
|
+
this.manager.cursor.togglePrecise('selection_nodes', false);
|
42
|
+
});
|
43
|
+
map.on('click', (e) => {
|
44
|
+
if (!e.originalEvent.shiftKey)
|
45
|
+
this.selectElement();
|
46
|
+
e.preventDefault();
|
47
|
+
});
|
48
|
+
}
|
49
|
+
selectElement(element) {
|
50
|
+
if (element == get(this.selectedElement))
|
51
|
+
return;
|
52
|
+
const elements = get(this.manager.elements);
|
53
|
+
elements.forEach((e) => e.select(e == element));
|
54
|
+
this.selectedElement.set(element);
|
55
|
+
this.updateSelectionNodes();
|
56
|
+
}
|
57
|
+
updateSelectionNodes() {
|
58
|
+
const nodes = get(this.selectedElement)?.getSelectionNodes() ?? [];
|
59
|
+
if (!this.selectionNodes)
|
60
|
+
this.selectionNodes = this.manager.map.getSource('selection_nodes');
|
61
|
+
this.selectionNodes?.setData({
|
62
|
+
type: 'FeatureCollection',
|
63
|
+
features: nodes.map((n) => ({
|
64
|
+
type: 'Feature',
|
65
|
+
properties: { index: n.index, opacity: n.transparent ? 0.3 : 1 },
|
66
|
+
geometry: { type: 'Point', coordinates: n.coordinates }
|
67
|
+
}))
|
68
|
+
});
|
69
|
+
}
|
70
|
+
}
|
@@ -11,12 +11,11 @@ for (let i = 0; i < BASE64_CHARS.length; i++) {
|
|
11
11
|
];
|
12
12
|
}
|
13
13
|
export const CHAR_VALUE2CODE = [
|
14
|
-
32, 101, 116, 97, 110, 105, 111, 115, 114, 108, 100, 104, 99, 117, 109, 112, 102, 103, 46, 121,
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
29, 30, 31, 35, 37, 92, 96, 124, 125, 127
|
14
|
+
32, 101, 116, 97, 110, 105, 111, 115, 114, 108, 100, 104, 99, 117, 109, 112, 102, 103, 46, 121, 98, 119, 44, 118, 48,
|
15
|
+
107, 49, 83, 84, 67, 50, 56, 53, 65, 57, 120, 51, 73, 45, 54, 52, 55, 77, 66, 34, 39, 80, 69, 78, 70, 82, 68, 85, 113,
|
16
|
+
76, 71, 74, 72, 79, 87, 106, 122, 47, 60, 62, 75, 41, 40, 86, 89, 58, 81, 90, 88, 59, 63, 94, 38, 43, 91, 93, 36, 33,
|
17
|
+
42, 61, 126, 95, 123, 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
|
18
|
+
25, 26, 27, 28, 29, 30, 31, 35, 37, 92, 96, 124, 125, 127
|
20
19
|
];
|
21
20
|
export const CHAR_CODE2VALUE = [];
|
22
21
|
CHAR_VALUE2CODE.forEach((c, v) => (CHAR_CODE2VALUE[c] = v));
|