@versatiles/svelte 1.0.0 → 1.0.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/dist/components/BBoxMap/AutoComplete.svelte +116 -89
- package/dist/components/BBoxMap/BBoxMap.svelte +52 -42
- package/dist/components/BBoxMap/BBoxMap.svelte.d.ts +5 -3
- package/dist/components/BasicMap/BasicMap.svelte +59 -34
- package/dist/components/LocatorMap/LocatorMap.svelte +67 -60
- package/dist/components/MapEditor/MapEditor.svelte +35 -80
- package/dist/components/MapEditor/components/Editor.svelte +53 -0
- package/dist/components/MapEditor/{Editor.svelte.d.ts → components/Editor.svelte.d.ts} +1 -1
- package/dist/components/MapEditor/components/EditorFill.svelte +28 -0
- package/dist/components/MapEditor/components/EditorFill.svelte.d.ts +7 -0
- package/dist/components/MapEditor/components/EditorStroke.svelte +28 -0
- package/dist/components/MapEditor/components/EditorStroke.svelte.d.ts +7 -0
- package/dist/components/MapEditor/components/EditorSymbol.svelte +43 -0
- package/dist/components/MapEditor/components/EditorSymbol.svelte.d.ts +7 -0
- package/dist/components/MapEditor/components/Sidebar.svelte +179 -0
- package/dist/components/MapEditor/components/Sidebar.svelte.d.ts +8 -0
- package/dist/components/MapEditor/components/SymbolSelector.svelte +118 -0
- package/dist/components/MapEditor/components/SymbolSelector.svelte.d.ts +8 -0
- package/dist/components/MapEditor/lib/__mocks__/cursor.d.ts +5 -0
- package/dist/components/MapEditor/lib/__mocks__/cursor.js +6 -0
- package/dist/components/MapEditor/lib/__mocks__/geometry_manager.d.ts +22 -0
- package/dist/components/MapEditor/lib/__mocks__/geometry_manager.js +21 -0
- package/dist/components/MapEditor/lib/__mocks__/map.d.ts +36 -0
- package/dist/components/MapEditor/lib/__mocks__/map.js +26 -0
- package/dist/components/MapEditor/lib/cursor.d.ts +9 -0
- package/dist/components/MapEditor/lib/cursor.js +31 -0
- package/dist/components/MapEditor/lib/element/abstract.d.ts +21 -0
- package/dist/components/MapEditor/lib/element/abstract.js +39 -0
- package/dist/components/MapEditor/lib/element/abstract_path.d.ts +11 -0
- package/dist/components/MapEditor/lib/element/abstract_path.js +79 -0
- package/dist/components/MapEditor/lib/element/line.d.ts +16 -0
- package/dist/components/MapEditor/lib/element/line.js +53 -0
- package/dist/components/MapEditor/lib/element/marker.d.ts +18 -0
- package/dist/components/MapEditor/lib/element/marker.js +62 -0
- package/dist/components/MapEditor/lib/element/polygon.d.ts +17 -0
- package/dist/components/MapEditor/lib/element/polygon.js +63 -0
- package/dist/components/MapEditor/lib/element/types.d.ts +11 -0
- package/dist/components/MapEditor/lib/geometry_manager.d.ts +20 -10
- package/dist/components/MapEditor/lib/geometry_manager.js +158 -57
- package/dist/components/MapEditor/lib/map_layer/abstract.d.ts +30 -0
- package/dist/components/MapEditor/lib/map_layer/abstract.js +90 -0
- package/dist/components/MapEditor/lib/map_layer/fill.d.ts +24 -0
- package/dist/components/MapEditor/lib/map_layer/fill.js +104 -0
- package/dist/components/MapEditor/lib/map_layer/line.d.ts +20 -0
- package/dist/components/MapEditor/lib/map_layer/line.js +90 -0
- package/dist/components/MapEditor/lib/map_layer/symbol.d.ts +19 -0
- package/dist/components/MapEditor/lib/map_layer/symbol.js +123 -0
- package/dist/components/MapEditor/lib/{types.d.ts → map_layer/types.d.ts} +7 -15
- package/dist/components/MapEditor/lib/map_layer/types.js +1 -0
- package/dist/components/MapEditor/lib/state/reader.d.ts +17 -0
- package/dist/components/MapEditor/lib/state/reader.js +161 -0
- package/dist/components/MapEditor/lib/state/types.d.ts +20 -0
- package/dist/components/MapEditor/lib/state/types.js +1 -0
- package/dist/components/MapEditor/lib/state/writer.d.ts +17 -0
- package/dist/components/MapEditor/lib/state/writer.js +178 -0
- package/dist/components/MapEditor/lib/symbols.d.ts +16 -0
- package/dist/components/MapEditor/lib/symbols.js +173 -0
- package/dist/components/MapEditor/lib/utils.d.ts +8 -1
- package/dist/components/MapEditor/lib/utils.js +33 -2
- package/dist/utils/draw/bbox.d.ts +3 -1
- package/dist/utils/draw/bbox.js +56 -51
- package/package.json +16 -16
- package/dist/components/MapEditor/Editor.svelte +0 -25
- package/dist/components/MapEditor/EditorLine.svelte +0 -27
- package/dist/components/MapEditor/EditorLine.svelte.d.ts +0 -7
- package/dist/components/MapEditor/EditorMarker.svelte +0 -42
- package/dist/components/MapEditor/EditorMarker.svelte.d.ts +0 -7
- package/dist/components/MapEditor/editor.scss +0 -16
- package/dist/components/MapEditor/lib/element_abstract.d.ts +0 -20
- package/dist/components/MapEditor/lib/element_abstract.js +0 -58
- package/dist/components/MapEditor/lib/element_line.d.ts +0 -14
- package/dist/components/MapEditor/lib/element_line.js +0 -76
- package/dist/components/MapEditor/lib/element_marker.d.ts +0 -20
- package/dist/components/MapEditor/lib/element_marker.js +0 -191
- package/dist/components/MapEditor/lib/map_layer.d.ts +0 -14
- package/dist/components/MapEditor/lib/map_layer.js +0 -61
- package/dist/utils/sprite_library.d.ts +0 -19
- package/dist/utils/sprite_library.js +0 -30
- /package/dist/components/MapEditor/lib/{types.js → element/types.js} +0 -0
@@ -1,21 +1,30 @@
|
|
1
1
|
import { get, writable } from 'svelte/store';
|
2
|
-
import { MarkerElement } from './
|
3
|
-
import { LineElement } from './
|
2
|
+
import { MarkerElement } from './element/marker.js';
|
3
|
+
import { LineElement } from './element/line.js';
|
4
|
+
import { PolygonElement } from './element/polygon.js';
|
5
|
+
import { Cursor } from './cursor.js';
|
6
|
+
import { StateWriter } from './state/writer.js';
|
7
|
+
import { StateReader } from './state/reader.js';
|
8
|
+
import { SymbolLibrary } from './symbols.js';
|
4
9
|
export class GeometryManager {
|
5
10
|
elements;
|
6
11
|
map;
|
7
|
-
|
8
|
-
selection_nodes;
|
12
|
+
selectedElement = writable(undefined);
|
9
13
|
canvas;
|
14
|
+
cursor;
|
15
|
+
symbolLibrary;
|
16
|
+
selectionNodes;
|
10
17
|
constructor(map) {
|
11
18
|
this.elements = writable([]);
|
12
19
|
this.map = map;
|
13
20
|
this.canvas = this.map.getCanvasContainer();
|
21
|
+
this.cursor = new Cursor(this.canvas);
|
22
|
+
this.symbolLibrary = new SymbolLibrary(map);
|
14
23
|
map.addSource('selection_nodes', {
|
15
24
|
type: 'geojson',
|
16
25
|
data: { type: 'FeatureCollection', features: [] }
|
17
26
|
});
|
18
|
-
this.
|
27
|
+
this.selectionNodes = map.getSource('selection_nodes');
|
19
28
|
map.addLayer({
|
20
29
|
id: 'selection_nodes',
|
21
30
|
source: 'selection_nodes',
|
@@ -24,54 +33,62 @@ export class GeometryManager {
|
|
24
33
|
paint: {
|
25
34
|
'circle-color': '#ffffff',
|
26
35
|
'circle-opacity': ['get', 'opacity'],
|
27
|
-
'circle-radius':
|
36
|
+
'circle-radius': 3,
|
28
37
|
'circle-stroke-color': '#000000',
|
29
38
|
'circle-stroke-opacity': ['get', 'opacity'],
|
30
|
-
'circle-stroke-width': 1
|
39
|
+
'circle-stroke-width': 1
|
31
40
|
}
|
32
41
|
});
|
33
42
|
map.on('mousedown', 'selection_nodes', (e) => {
|
34
|
-
const element = get(this.
|
43
|
+
const element = get(this.selectedElement);
|
35
44
|
if (element == undefined)
|
36
45
|
return;
|
37
46
|
const feature = map.queryRenderedFeatures(e.point, { layers: ['selection_nodes'] })[0];
|
38
|
-
const
|
39
|
-
if (
|
47
|
+
const selectedNode = element.getSelectionNodeUpdater(feature.properties);
|
48
|
+
if (selectedNode == undefined)
|
40
49
|
return;
|
50
|
+
// @ts-expect-error ensure that the event is ignored by other layers
|
51
|
+
e.ignore = true;
|
41
52
|
e.preventDefault();
|
42
|
-
|
43
|
-
|
44
|
-
this.
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
53
|
+
if (e.originalEvent.shiftKey) {
|
54
|
+
selectedNode.delete();
|
55
|
+
this.drawSelectionNodes();
|
56
|
+
this.saveState();
|
57
|
+
}
|
58
|
+
else {
|
59
|
+
const onMove = (e) => {
|
60
|
+
e.preventDefault();
|
61
|
+
selectedNode.update(e.lngLat.lng, e.lngLat.lat);
|
62
|
+
this.drawSelectionNodes();
|
63
|
+
};
|
64
|
+
map.on('mousemove', onMove);
|
65
|
+
map.once('mouseup', () => {
|
66
|
+
this.saveState();
|
67
|
+
map.off('mousemove', onMove);
|
68
|
+
});
|
69
|
+
}
|
54
70
|
});
|
55
|
-
map.on('
|
56
|
-
map.on('
|
71
|
+
map.on('mouseenter', 'selection_nodes', () => this.cursor.precise(true));
|
72
|
+
map.on('mouseleave', 'selection_nodes', () => this.cursor.precise(false));
|
57
73
|
map.on('click', (e) => {
|
58
|
-
|
74
|
+
if (!e.originalEvent.shiftKey)
|
75
|
+
this.selectElement(undefined);
|
59
76
|
e.preventDefault();
|
60
77
|
});
|
78
|
+
map.on('moveend', () => this.saveState());
|
79
|
+
const hash = location.hash.slice(1);
|
80
|
+
if (hash)
|
81
|
+
this.loadState(hash);
|
61
82
|
}
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
}
|
68
|
-
else {
|
69
|
-
this.drawSelectionNodes([]);
|
70
|
-
}
|
71
|
-
this.activeElement.set(element);
|
83
|
+
selectElement(element) {
|
84
|
+
const elements = get(this.elements);
|
85
|
+
elements.forEach((e) => e.select(e == element));
|
86
|
+
this.selectedElement.set(element);
|
87
|
+
this.drawSelectionNodes();
|
72
88
|
}
|
73
|
-
drawSelectionNodes(
|
74
|
-
this.
|
89
|
+
drawSelectionNodes() {
|
90
|
+
const nodes = get(this.selectedElement)?.getSelectionNodes() ?? [];
|
91
|
+
this.selectionNodes.setData({
|
75
92
|
type: 'FeatureCollection',
|
76
93
|
features: nodes.map((n) => ({
|
77
94
|
type: 'Feature',
|
@@ -80,38 +97,122 @@ export class GeometryManager {
|
|
80
97
|
}))
|
81
98
|
});
|
82
99
|
}
|
100
|
+
getState() {
|
101
|
+
const center = this.map.getCenter();
|
102
|
+
return {
|
103
|
+
map: {
|
104
|
+
point: [center.lng, center.lat],
|
105
|
+
zoom: this.map.getZoom()
|
106
|
+
},
|
107
|
+
elements: get(this.elements).map((element) => element.getState())
|
108
|
+
};
|
109
|
+
}
|
110
|
+
async saveState() {
|
111
|
+
const writer = new StateWriter();
|
112
|
+
writer.writeObject(this.getState());
|
113
|
+
location.hash = await writer.getBase64compressed();
|
114
|
+
}
|
115
|
+
async loadState(hash) {
|
116
|
+
if (!hash)
|
117
|
+
return;
|
118
|
+
try {
|
119
|
+
const reader = await StateReader.fromBase64compressed(hash);
|
120
|
+
const state = reader.readObject();
|
121
|
+
if (!state)
|
122
|
+
return;
|
123
|
+
if (state.map?.zoom)
|
124
|
+
this.map.setZoom(state.map.zoom);
|
125
|
+
if (state.map?.point) {
|
126
|
+
this.map.setCenter({ lng: state.map.point[0], lat: state.map.point[1] });
|
127
|
+
}
|
128
|
+
if (state.elements) {
|
129
|
+
this.elements.set(state.elements.map((element) => {
|
130
|
+
switch (element.type) {
|
131
|
+
case 'marker':
|
132
|
+
return MarkerElement.fromState(this, element);
|
133
|
+
case 'line':
|
134
|
+
return LineElement.fromState(this, element);
|
135
|
+
case 'polygon':
|
136
|
+
return PolygonElement.fromState(this, element);
|
137
|
+
default:
|
138
|
+
throw new Error('Unknown element type');
|
139
|
+
}
|
140
|
+
}));
|
141
|
+
}
|
142
|
+
}
|
143
|
+
catch (error) {
|
144
|
+
console.error(error);
|
145
|
+
}
|
146
|
+
}
|
83
147
|
getElement(index) {
|
84
148
|
return get(this.elements)[index];
|
85
149
|
}
|
86
|
-
|
87
|
-
const element = new MarkerElement(this
|
150
|
+
addNewMarker() {
|
151
|
+
const element = new MarkerElement(this);
|
88
152
|
this.addElement(element);
|
89
153
|
return element;
|
90
154
|
}
|
91
|
-
|
92
|
-
const element = new LineElement(this
|
155
|
+
addNewLine() {
|
156
|
+
const element = new LineElement(this);
|
157
|
+
this.addElement(element);
|
158
|
+
return element;
|
159
|
+
}
|
160
|
+
addNewPolygon() {
|
161
|
+
const element = new PolygonElement(this);
|
93
162
|
this.addElement(element);
|
94
163
|
return element;
|
95
164
|
}
|
96
165
|
addElement(element) {
|
97
166
|
this.elements.update((elements) => [...elements, element]);
|
167
|
+
this.saveState();
|
98
168
|
}
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
169
|
+
deleteElement(element) {
|
170
|
+
this.elements.update((elements) => elements.filter((e) => e !== element));
|
171
|
+
if (get(this.selectedElement) === element)
|
172
|
+
this.selectElement(undefined);
|
173
|
+
this.saveState();
|
174
|
+
}
|
175
|
+
getGeoJSON() {
|
176
|
+
const center = this.map.getCenter();
|
177
|
+
return {
|
178
|
+
type: 'FeatureCollection',
|
179
|
+
map: {
|
180
|
+
center: [center.lng, center.lat],
|
181
|
+
zoom: this.map.getZoom()
|
182
|
+
},
|
183
|
+
features: get(this.elements).map((element) => element.getFeature(true))
|
184
|
+
};
|
185
|
+
}
|
186
|
+
addGeoJSON(geojson) {
|
187
|
+
if ('map' in geojson) {
|
188
|
+
const { map } = geojson;
|
189
|
+
if (typeof map.zoom === 'number') {
|
190
|
+
this.map.setZoom(map.zoom);
|
191
|
+
}
|
192
|
+
if (Array.isArray(map.center)) {
|
193
|
+
const [lng, lat] = map.center;
|
194
|
+
if (typeof lng === 'number' && typeof lat === 'number') {
|
195
|
+
this.map.setCenter({ lng, lat });
|
196
|
+
}
|
197
|
+
}
|
198
|
+
}
|
199
|
+
for (const feature of geojson.features) {
|
200
|
+
let element;
|
201
|
+
switch (feature.geometry.type) {
|
202
|
+
case 'Point':
|
203
|
+
element = MarkerElement.fromGeoJSON(this, feature);
|
204
|
+
break;
|
205
|
+
case 'LineString':
|
206
|
+
element = LineElement.fromGeoJSON(this, feature);
|
207
|
+
break;
|
208
|
+
case 'Polygon':
|
209
|
+
element = PolygonElement.fromGeoJSON(this, feature);
|
210
|
+
break;
|
211
|
+
default:
|
212
|
+
throw new Error(`Unknown geometry type "${feature.geometry.type}"`);
|
213
|
+
}
|
214
|
+
this.addElement(element);
|
114
215
|
}
|
115
|
-
|
216
|
+
this.saveState();
|
116
217
|
}
|
117
218
|
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import type { LayerFill, LayerLine, LayerSymbol } from './types.js';
|
2
|
+
import type { GeometryManager } from '../geometry_manager.js';
|
3
|
+
import type { StateObject } from '../state/types.js';
|
4
|
+
type LayerSpec = LayerFill | LayerLine | LayerSymbol;
|
5
|
+
type Events = 'click' | 'mousedown' | 'mousemove' | 'mouseup';
|
6
|
+
type MouseEventHandler = (event: maplibregl.MapMouseEvent) => void;
|
7
|
+
export declare abstract class MapLayer<T extends LayerSpec> {
|
8
|
+
private layout;
|
9
|
+
private paint;
|
10
|
+
protected readonly id: string;
|
11
|
+
readonly manager: GeometryManager;
|
12
|
+
protected readonly map: maplibregl.Map;
|
13
|
+
eventHandlers: Map<Events, MouseEventHandler[]>;
|
14
|
+
isSelected: boolean;
|
15
|
+
constructor(manager: GeometryManager, id: string);
|
16
|
+
addLayer(source: string, type: 'symbol' | 'line' | 'fill', layout: T['layout'], paint: T['paint']): void;
|
17
|
+
on(event: Events, handler: MouseEventHandler): void;
|
18
|
+
off(event: Events, handler: MouseEventHandler): void;
|
19
|
+
private dispatchEvent;
|
20
|
+
private addEvents;
|
21
|
+
setPaint(paint: T['paint']): void;
|
22
|
+
updatePaint<K extends keyof T['paint'], V extends T['paint'][K]>(key: K, value: V): void;
|
23
|
+
setLayout(layout: T['layout']): void;
|
24
|
+
updateLayout<K extends keyof T['layout'], V extends T['layout'][K]>(key: K, value: V): void;
|
25
|
+
destroy(): void;
|
26
|
+
abstract getState(): StateObject | undefined;
|
27
|
+
abstract getGeoJSONProperties(): GeoJSON.GeoJsonProperties;
|
28
|
+
abstract setGeoJSONProperties(properties: GeoJSON.GeoJsonProperties): void;
|
29
|
+
}
|
30
|
+
export {};
|
@@ -0,0 +1,90 @@
|
|
1
|
+
import { Color } from '@versatiles/style';
|
2
|
+
export class MapLayer {
|
3
|
+
layout = {};
|
4
|
+
paint = {};
|
5
|
+
id;
|
6
|
+
manager;
|
7
|
+
map;
|
8
|
+
eventHandlers = new Map();
|
9
|
+
isSelected = false;
|
10
|
+
constructor(manager, id) {
|
11
|
+
this.manager = manager;
|
12
|
+
this.map = manager.map;
|
13
|
+
this.id = id;
|
14
|
+
}
|
15
|
+
addLayer(source, type, layout, paint) {
|
16
|
+
this.layout = layout;
|
17
|
+
this.paint = paint;
|
18
|
+
this.map.addLayer({ id: this.id, source, type, layout, paint }, 'selection_nodes');
|
19
|
+
this.addEvents();
|
20
|
+
}
|
21
|
+
on(event, handler) {
|
22
|
+
if (!this.eventHandlers.has(event))
|
23
|
+
this.eventHandlers.set(event, []);
|
24
|
+
this.eventHandlers.get(event).push(handler);
|
25
|
+
}
|
26
|
+
off(event, handler) {
|
27
|
+
if (!this.eventHandlers.has(event))
|
28
|
+
return;
|
29
|
+
const handlers = this.eventHandlers.get(event);
|
30
|
+
this.eventHandlers.set(event, handlers.filter((h) => h !== handler));
|
31
|
+
}
|
32
|
+
dispatchEvent(event, e) {
|
33
|
+
const handlers = this.eventHandlers.get(event);
|
34
|
+
if (handlers)
|
35
|
+
handlers.forEach((handler) => handler(e));
|
36
|
+
}
|
37
|
+
addEvents() {
|
38
|
+
this.map.on('mouseenter', this.id, () => {
|
39
|
+
if (this.isSelected)
|
40
|
+
this.manager.cursor.grab(true);
|
41
|
+
this.manager.cursor.hover(true);
|
42
|
+
});
|
43
|
+
this.map.on('mouseleave', this.id, () => {
|
44
|
+
if (this.isSelected)
|
45
|
+
this.manager.cursor.grab(false);
|
46
|
+
this.manager.cursor.hover(false);
|
47
|
+
});
|
48
|
+
this.map.on('click', this.id, (e) => {
|
49
|
+
this.dispatchEvent('click', e);
|
50
|
+
if (this.isSelected)
|
51
|
+
this.manager.cursor.grab(true);
|
52
|
+
this.manager.cursor.hover(true);
|
53
|
+
e.preventDefault();
|
54
|
+
});
|
55
|
+
this.map.on('mousedown', this.id, (e) => this.dispatchEvent('mousedown', e));
|
56
|
+
this.map.on('mouseup', this.id, (e) => this.dispatchEvent('mouseup', e));
|
57
|
+
this.map.on('mousemove', this.id, (e) => this.dispatchEvent('mousemove', e));
|
58
|
+
}
|
59
|
+
setPaint(paint) {
|
60
|
+
if (paint === undefined)
|
61
|
+
return;
|
62
|
+
const keys = new Set(Object.keys(paint).concat(Object.keys(this.paint)));
|
63
|
+
for (const key of keys.values())
|
64
|
+
this.updatePaint(key, paint[key]);
|
65
|
+
}
|
66
|
+
updatePaint(key, value) {
|
67
|
+
if (value instanceof Color)
|
68
|
+
value = value.asString();
|
69
|
+
if (this.paint[key] == value)
|
70
|
+
return;
|
71
|
+
this.map.setPaintProperty(this.id, key, value);
|
72
|
+
this.paint[key] = value;
|
73
|
+
}
|
74
|
+
setLayout(layout) {
|
75
|
+
if (layout === undefined)
|
76
|
+
return;
|
77
|
+
const keys = new Set(Object.keys(layout).concat(Object.keys(this.layout)));
|
78
|
+
for (const key of keys.values())
|
79
|
+
this.updateLayout(key, layout[key]);
|
80
|
+
}
|
81
|
+
updateLayout(key, value) {
|
82
|
+
if (this.layout[key] == value)
|
83
|
+
return;
|
84
|
+
this.map.setLayoutProperty(this.id, key, value);
|
85
|
+
this.layout[key] = value;
|
86
|
+
}
|
87
|
+
destroy() {
|
88
|
+
this.map.removeLayer(this.id);
|
89
|
+
}
|
90
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import type { LayerFill } from './types.js';
|
2
|
+
import { MapLayer } from './abstract.js';
|
3
|
+
import type { GeometryManager } from '../geometry_manager.js';
|
4
|
+
import type { StateObject } from '../state/types.js';
|
5
|
+
interface Fill {
|
6
|
+
xf: number;
|
7
|
+
yf: number;
|
8
|
+
pattern: string;
|
9
|
+
}
|
10
|
+
export declare const fillPatterns: Map<number, {
|
11
|
+
name: string;
|
12
|
+
fill: Fill | undefined;
|
13
|
+
}>;
|
14
|
+
export declare class MapLayerFill extends MapLayer<LayerFill> {
|
15
|
+
color: import("svelte/store").Writable<string>;
|
16
|
+
opacity: import("svelte/store").Writable<number>;
|
17
|
+
pattern: import("svelte/store").Writable<number>;
|
18
|
+
constructor(manager: GeometryManager, id: string, source: string);
|
19
|
+
getState(): StateObject | undefined;
|
20
|
+
setState(state: StateObject): void;
|
21
|
+
getGeoJSONProperties(): GeoJSON.GeoJsonProperties;
|
22
|
+
setGeoJSONProperties(properties: GeoJSON.GeoJsonProperties): void;
|
23
|
+
}
|
24
|
+
export {};
|
@@ -0,0 +1,104 @@
|
|
1
|
+
import { get, writable } from 'svelte/store';
|
2
|
+
import { MapLayer } from './abstract.js';
|
3
|
+
import { Color } from '@versatiles/style';
|
4
|
+
import { removeDefaultFields } from '../utils.js';
|
5
|
+
const size = 32;
|
6
|
+
export const fillPatterns = new Map([
|
7
|
+
[0, { name: 'solid', fill: undefined }],
|
8
|
+
[1, { name: 'diagonal', fill: { xf: 1, yf: 1, pattern: '00002552' } }],
|
9
|
+
[2, { name: 'diagonal-thin', fill: { xf: 1, yf: 1, pattern: '0252' } }]
|
10
|
+
]);
|
11
|
+
export class MapLayerFill extends MapLayer {
|
12
|
+
color = writable('#ff0000');
|
13
|
+
opacity = writable(1);
|
14
|
+
pattern = writable(0);
|
15
|
+
constructor(manager, id, source) {
|
16
|
+
super(manager, id);
|
17
|
+
this.addLayer(source, 'fill', {}, {
|
18
|
+
'fill-color': Color.parse(get(this.color)).asHex(),
|
19
|
+
'fill-opacity': get(this.opacity)
|
20
|
+
});
|
21
|
+
const updatePattern = () => {
|
22
|
+
const fill = fillPatterns.get(get(this.pattern))?.fill ?? undefined;
|
23
|
+
const color = Color.parse(get(this.color));
|
24
|
+
if (fill == null) {
|
25
|
+
this.updatePaint('fill-color', color);
|
26
|
+
this.updatePaint('fill-pattern', undefined);
|
27
|
+
return;
|
28
|
+
}
|
29
|
+
const { xf, yf, pattern: p } = fill;
|
30
|
+
const alpha = p.split('').map((c) => parseInt(c, 10) * 51);
|
31
|
+
const length = alpha.length;
|
32
|
+
const data = new Uint8ClampedArray(size * size * 4);
|
33
|
+
const c = color.asRGB().asArray();
|
34
|
+
for (let y = 0; y < size; y++) {
|
35
|
+
for (let x = 0; x < size; x++) {
|
36
|
+
const v = x * xf + y * yf;
|
37
|
+
const i = (y * size + x) * 4;
|
38
|
+
data[i] = c[0];
|
39
|
+
data[i + 1] = c[1];
|
40
|
+
data[i + 2] = c[2];
|
41
|
+
data[i + 3] = alpha[v % length];
|
42
|
+
}
|
43
|
+
}
|
44
|
+
const name = 'fill-pattern-' + this.id;
|
45
|
+
if (this.map.hasImage(name))
|
46
|
+
this.map.removeImage(name);
|
47
|
+
this.map.addImage(name, { width: size, height: size, data });
|
48
|
+
this.updatePaint('fill-pattern', name);
|
49
|
+
};
|
50
|
+
this.color.subscribe(() => {
|
51
|
+
updatePattern();
|
52
|
+
this.manager.saveState();
|
53
|
+
});
|
54
|
+
this.pattern.subscribe(() => {
|
55
|
+
updatePattern();
|
56
|
+
this.manager.saveState();
|
57
|
+
});
|
58
|
+
this.opacity.subscribe((value) => {
|
59
|
+
this.updatePaint('fill-opacity', value);
|
60
|
+
this.manager.saveState();
|
61
|
+
});
|
62
|
+
}
|
63
|
+
getState() {
|
64
|
+
return removeDefaultFields({
|
65
|
+
color: get(this.color),
|
66
|
+
opacity: get(this.opacity),
|
67
|
+
pattern: get(this.pattern)
|
68
|
+
}, {
|
69
|
+
color: '#ff0000',
|
70
|
+
opacity: 1,
|
71
|
+
pattern: 0
|
72
|
+
});
|
73
|
+
}
|
74
|
+
setState(state) {
|
75
|
+
if (state.color)
|
76
|
+
this.color.set(state.color);
|
77
|
+
if (state.opacity)
|
78
|
+
this.opacity.set(state.opacity);
|
79
|
+
if (state.pattern)
|
80
|
+
this.pattern.set(state.pattern);
|
81
|
+
}
|
82
|
+
getGeoJSONProperties() {
|
83
|
+
return {
|
84
|
+
'fill-color': get(this.color),
|
85
|
+
'fill-opacity': get(this.opacity),
|
86
|
+
'fill-pattern': fillPatterns.get(get(this.pattern))?.name
|
87
|
+
};
|
88
|
+
}
|
89
|
+
setGeoJSONProperties(properties) {
|
90
|
+
if (properties == null)
|
91
|
+
return;
|
92
|
+
if (properties['fill-color'])
|
93
|
+
this.color.set(properties['fill-color']);
|
94
|
+
if (properties['fill-opacity'])
|
95
|
+
this.opacity.set(properties['fill-opacity']);
|
96
|
+
if (properties['fill-pattern']) {
|
97
|
+
const pattern = fillPatterns
|
98
|
+
.entries()
|
99
|
+
.find(([, { name }]) => name === properties['fill-pattern']);
|
100
|
+
if (pattern)
|
101
|
+
this.pattern.set(pattern[0]);
|
102
|
+
}
|
103
|
+
}
|
104
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import type { LayerLine } from './types.js';
|
2
|
+
import { MapLayer } from './abstract.js';
|
3
|
+
import type { GeometryManager } from '../geometry_manager.js';
|
4
|
+
import type { StateObject } from '../state/types.js';
|
5
|
+
export declare const dashArrays: Map<number, {
|
6
|
+
name: string;
|
7
|
+
array: number[] | undefined;
|
8
|
+
}>;
|
9
|
+
export declare class MapLayerLine extends MapLayer<LayerLine> {
|
10
|
+
color: import("svelte/store").Writable<string>;
|
11
|
+
dashed: import("svelte/store").Writable<number>;
|
12
|
+
visible: import("svelte/store").Writable<boolean>;
|
13
|
+
width: import("svelte/store").Writable<number>;
|
14
|
+
dashArray: import("svelte/store").Readable<number[]>;
|
15
|
+
constructor(manager: GeometryManager, id: string, source: string);
|
16
|
+
getState(): StateObject | undefined;
|
17
|
+
setState(state: StateObject): void;
|
18
|
+
getGeoJSONProperties(): GeoJSON.GeoJsonProperties;
|
19
|
+
setGeoJSONProperties(properties: GeoJSON.GeoJsonProperties): void;
|
20
|
+
}
|
@@ -0,0 +1,90 @@
|
|
1
|
+
import { derived, get, writable } from 'svelte/store';
|
2
|
+
import { MapLayer } from './abstract.js';
|
3
|
+
import { Color } from '@versatiles/style';
|
4
|
+
import { removeDefaultFields } from '../utils.js';
|
5
|
+
export const dashArrays = new Map([
|
6
|
+
[0, { name: 'solid', array: [100] }],
|
7
|
+
[1, { name: 'dashed', array: [2, 4] }],
|
8
|
+
[2, { name: 'dotted', array: [0, 2] }]
|
9
|
+
]);
|
10
|
+
export class MapLayerLine extends MapLayer {
|
11
|
+
color = writable('#ff0000');
|
12
|
+
dashed = writable(0);
|
13
|
+
visible = writable(true);
|
14
|
+
width = writable(2);
|
15
|
+
dashArray = derived(this.dashed, (dashed) => dashArrays.get(dashed)?.array ?? [100]);
|
16
|
+
constructor(manager, id, source) {
|
17
|
+
super(manager, id);
|
18
|
+
this.addLayer(source, 'line', {
|
19
|
+
'line-cap': 'round',
|
20
|
+
'line-join': 'round',
|
21
|
+
visibility: get(this.visible) ? 'visible' : 'none'
|
22
|
+
}, {
|
23
|
+
'line-color': Color.parse(get(this.color)).asHex(),
|
24
|
+
'line-dasharray': get(this.dashArray),
|
25
|
+
'line-width': get(this.width)
|
26
|
+
});
|
27
|
+
this.color.subscribe((v) => {
|
28
|
+
this.updatePaint('line-color', Color.parse(v));
|
29
|
+
this.manager.saveState();
|
30
|
+
});
|
31
|
+
this.dashArray.subscribe((v) => {
|
32
|
+
this.updatePaint('line-dasharray', v);
|
33
|
+
this.manager.saveState();
|
34
|
+
});
|
35
|
+
this.visible.subscribe((v) => {
|
36
|
+
this.updateLayout('visibility', v ? 'visible' : 'none');
|
37
|
+
this.manager.saveState();
|
38
|
+
});
|
39
|
+
this.width.subscribe((v) => {
|
40
|
+
this.updatePaint('line-width', v);
|
41
|
+
this.manager.saveState();
|
42
|
+
});
|
43
|
+
}
|
44
|
+
getState() {
|
45
|
+
return removeDefaultFields({
|
46
|
+
color: get(this.color),
|
47
|
+
pattern: get(this.dashed),
|
48
|
+
visible: get(this.visible),
|
49
|
+
width: get(this.width)
|
50
|
+
}, {
|
51
|
+
color: '#ff0000',
|
52
|
+
pattern: 0,
|
53
|
+
visible: true,
|
54
|
+
width: 2
|
55
|
+
});
|
56
|
+
}
|
57
|
+
setState(state) {
|
58
|
+
if (state.color)
|
59
|
+
this.color.set(state.color);
|
60
|
+
if (state.pattern)
|
61
|
+
this.dashed.set(state.pattern);
|
62
|
+
if (state.visible)
|
63
|
+
this.visible.set(state.visible);
|
64
|
+
if (state.width)
|
65
|
+
this.width.set(state.width);
|
66
|
+
}
|
67
|
+
getGeoJSONProperties() {
|
68
|
+
return {
|
69
|
+
'stroke-color': get(this.color),
|
70
|
+
'stroke-style': dashArrays.get(get(this.dashed))?.name,
|
71
|
+
'stroke-width': get(this.width),
|
72
|
+
'stroke-visibility': get(this.visible)
|
73
|
+
};
|
74
|
+
}
|
75
|
+
setGeoJSONProperties(properties) {
|
76
|
+
if (properties == null)
|
77
|
+
return;
|
78
|
+
if (properties['stroke-color'])
|
79
|
+
this.color.set(properties['stroke-color']);
|
80
|
+
if (properties['stroke-style']) {
|
81
|
+
const dash = dashArrays.entries().find(([, { name }]) => name === properties['stroke-style']);
|
82
|
+
if (dash)
|
83
|
+
this.dashed.set(dash[0]);
|
84
|
+
}
|
85
|
+
if (properties['stroke-width'])
|
86
|
+
this.width.set(properties['stroke-width']);
|
87
|
+
if (properties['stroke-visibility'])
|
88
|
+
this.visible.set(properties['stroke-visibility']);
|
89
|
+
}
|
90
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import type { LayerSymbol } from './types.js';
|
2
|
+
import { MapLayer } from './abstract.js';
|
3
|
+
import type { GeometryManager } from '../geometry_manager.js';
|
4
|
+
import type { StateObject } from '../state/types.js';
|
5
|
+
export declare class MapLayerSymbol extends MapLayer<LayerSymbol> {
|
6
|
+
color: import("svelte/store").Writable<string>;
|
7
|
+
halo: import("svelte/store").Writable<number>;
|
8
|
+
rotate: import("svelte/store").Writable<number>;
|
9
|
+
size: import("svelte/store").Writable<number>;
|
10
|
+
symbolIndex: import("svelte/store").Writable<number>;
|
11
|
+
label: import("svelte/store").Writable<string>;
|
12
|
+
haloWidth: import("svelte/store").Readable<number>;
|
13
|
+
symbolInfo: import("svelte/store").Readable<import("../symbols.js").SymbolInfo>;
|
14
|
+
constructor(manager: GeometryManager, id: string, source: string);
|
15
|
+
getState(): StateObject | undefined;
|
16
|
+
setState(state: StateObject): void;
|
17
|
+
getGeoJSONProperties(): GeoJSON.GeoJsonProperties;
|
18
|
+
setGeoJSONProperties(properties: GeoJSON.GeoJsonProperties): void;
|
19
|
+
}
|