@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
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { writable } from 'svelte/store';
|
|
2
|
+
import { vi } from 'vitest';
|
|
3
|
+
import { MockMap } from './map.js';
|
|
4
|
+
import { MockCursor } from './cursor.js';
|
|
5
|
+
export class MockGeometryManager {
|
|
6
|
+
elements = writable([]);
|
|
7
|
+
activeElement = writable(undefined);
|
|
8
|
+
map = new MockMap();
|
|
9
|
+
cursor = new MockCursor();
|
|
10
|
+
constructor() { }
|
|
11
|
+
setActiveElement = vi.fn();
|
|
12
|
+
getState = vi.fn(() => ({ map: { point: [0, 0], zoom: 10 }, elements: [] }));
|
|
13
|
+
saveState = vi.fn();
|
|
14
|
+
loadState = vi.fn();
|
|
15
|
+
getElement = vi.fn((index) => ({ index }));
|
|
16
|
+
addNewMarker = vi.fn(() => ({}));
|
|
17
|
+
addNewLine = vi.fn(() => ({}));
|
|
18
|
+
addNewPolygon = vi.fn(() => ({}));
|
|
19
|
+
deleteElement = vi.fn();
|
|
20
|
+
drawSelectionNodes = vi.fn();
|
|
21
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export declare class MockMap {
|
|
2
|
+
getCanvasContainer: import("vitest").Mock<() => {
|
|
3
|
+
style: {
|
|
4
|
+
cursor: string;
|
|
5
|
+
};
|
|
6
|
+
}>;
|
|
7
|
+
addSource: import("vitest").Mock<(...args: any[]) => any>;
|
|
8
|
+
removeSource: import("vitest").Mock<(...args: any[]) => any>;
|
|
9
|
+
getSource: import("vitest").Mock<() => {
|
|
10
|
+
setData: import("vitest").Mock<(...args: any[]) => any>;
|
|
11
|
+
}>;
|
|
12
|
+
addLayer: import("vitest").Mock<(...args: any[]) => any>;
|
|
13
|
+
on: import("vitest").Mock<(...args: any[]) => any>;
|
|
14
|
+
setCenter: import("vitest").Mock<(...args: any[]) => any>;
|
|
15
|
+
setZoom: import("vitest").Mock<(...args: any[]) => any>;
|
|
16
|
+
getZoom: import("vitest").Mock<() => number>;
|
|
17
|
+
getCenter: import("vitest").Mock<() => {
|
|
18
|
+
lng: number;
|
|
19
|
+
lat: number;
|
|
20
|
+
}>;
|
|
21
|
+
queryRenderedFeatures: import("vitest").Mock<() => {
|
|
22
|
+
properties: {};
|
|
23
|
+
}[]>;
|
|
24
|
+
setPaintProperty: import("vitest").Mock<(...args: any[]) => any>;
|
|
25
|
+
setLayoutProperty: import("vitest").Mock<(...args: any[]) => any>;
|
|
26
|
+
removeLayer: import("vitest").Mock<(...args: any[]) => any>;
|
|
27
|
+
hasImage: import("vitest").Mock<(...args: any[]) => any>;
|
|
28
|
+
removeImage: import("vitest").Mock<(...args: any[]) => any>;
|
|
29
|
+
addImage: import("vitest").Mock<(...args: any[]) => any>;
|
|
30
|
+
getBounds: import("vitest").Mock<() => {
|
|
31
|
+
getWest: () => -180;
|
|
32
|
+
getEast: () => 180;
|
|
33
|
+
getSouth: () => -90;
|
|
34
|
+
getNorth: () => 90;
|
|
35
|
+
}>;
|
|
36
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { vi } from 'vitest';
|
|
2
|
+
export class MockMap {
|
|
3
|
+
getCanvasContainer = vi.fn(() => ({ style: { cursor: 'default' } }));
|
|
4
|
+
addSource = vi.fn();
|
|
5
|
+
removeSource = vi.fn();
|
|
6
|
+
getSource = vi.fn(() => ({ setData: vi.fn() }));
|
|
7
|
+
addLayer = vi.fn();
|
|
8
|
+
on = vi.fn();
|
|
9
|
+
setCenter = vi.fn();
|
|
10
|
+
setZoom = vi.fn();
|
|
11
|
+
getZoom = vi.fn(() => 10);
|
|
12
|
+
getCenter = vi.fn(() => ({ lng: 0, lat: 0 }));
|
|
13
|
+
queryRenderedFeatures = vi.fn(() => [{ properties: {} }]);
|
|
14
|
+
setPaintProperty = vi.fn();
|
|
15
|
+
setLayoutProperty = vi.fn();
|
|
16
|
+
removeLayer = vi.fn();
|
|
17
|
+
hasImage = vi.fn();
|
|
18
|
+
removeImage = vi.fn();
|
|
19
|
+
addImage = vi.fn();
|
|
20
|
+
getBounds = vi.fn(() => ({
|
|
21
|
+
getWest: () => -180,
|
|
22
|
+
getEast: () => 180,
|
|
23
|
+
getSouth: () => -90,
|
|
24
|
+
getNorth: () => 90
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export class Cursor {
|
|
2
|
+
element;
|
|
3
|
+
#hover = 0;
|
|
4
|
+
#precise = 0;
|
|
5
|
+
#grab = 0;
|
|
6
|
+
constructor(element) {
|
|
7
|
+
this.element = element;
|
|
8
|
+
this.update();
|
|
9
|
+
}
|
|
10
|
+
update() {
|
|
11
|
+
if (this.#precise > 0)
|
|
12
|
+
return (this.element.style.cursor = 'crosshair');
|
|
13
|
+
if (this.#grab > 0)
|
|
14
|
+
return (this.element.style.cursor = 'grab');
|
|
15
|
+
if (this.#hover > 0)
|
|
16
|
+
return (this.element.style.cursor = 'pointer');
|
|
17
|
+
this.element.style.cursor = 'default';
|
|
18
|
+
}
|
|
19
|
+
hover(increase) {
|
|
20
|
+
this.#hover = Math.max(0, this.#hover + (increase ? 1 : -1));
|
|
21
|
+
this.update();
|
|
22
|
+
}
|
|
23
|
+
precise(increase) {
|
|
24
|
+
this.#precise = Math.max(0, this.#precise + (increase ? 1 : -1));
|
|
25
|
+
this.update();
|
|
26
|
+
}
|
|
27
|
+
grab(increase) {
|
|
28
|
+
this.#grab = Math.max(0, this.#grab + (increase ? 1 : -1));
|
|
29
|
+
this.update();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ElementPoint, SelectionNode, SelectionNodeUpdater } from './types.js';
|
|
2
|
+
import type { GeometryManager } from '../geometry_manager.js';
|
|
3
|
+
import type { StateObject } from '../state/types.js';
|
|
4
|
+
export declare abstract class AbstractElement {
|
|
5
|
+
protected readonly canvas: HTMLElement;
|
|
6
|
+
protected readonly manager: GeometryManager;
|
|
7
|
+
protected readonly map: maplibregl.Map;
|
|
8
|
+
protected readonly source: maplibregl.GeoJSONSource;
|
|
9
|
+
protected readonly slug: string;
|
|
10
|
+
protected isSelected: boolean;
|
|
11
|
+
readonly sourceId: string;
|
|
12
|
+
constructor(manager: GeometryManager);
|
|
13
|
+
select(value: boolean): void;
|
|
14
|
+
protected randomPositions(length: number): ElementPoint[];
|
|
15
|
+
delete(): void;
|
|
16
|
+
abstract destroy(): void;
|
|
17
|
+
abstract getFeature(includeProperties: boolean): GeoJSON.Feature;
|
|
18
|
+
abstract getSelectionNodes(): SelectionNode[];
|
|
19
|
+
abstract getSelectionNodeUpdater(properties?: Record<string, unknown>): SelectionNodeUpdater | undefined;
|
|
20
|
+
abstract getState(): StateObject;
|
|
21
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export class AbstractElement {
|
|
2
|
+
canvas;
|
|
3
|
+
manager;
|
|
4
|
+
map;
|
|
5
|
+
source;
|
|
6
|
+
slug = '_' + Math.random().toString(36).slice(2);
|
|
7
|
+
isSelected = false;
|
|
8
|
+
sourceId = 'source' + this.slug;
|
|
9
|
+
constructor(manager) {
|
|
10
|
+
this.manager = manager;
|
|
11
|
+
this.map = manager.map;
|
|
12
|
+
this.canvas = this.map.getCanvasContainer();
|
|
13
|
+
this.map.addSource(this.sourceId, {
|
|
14
|
+
type: 'geojson',
|
|
15
|
+
data: { type: 'FeatureCollection', features: [] }
|
|
16
|
+
});
|
|
17
|
+
this.source = this.map.getSource(this.sourceId);
|
|
18
|
+
}
|
|
19
|
+
select(value) {
|
|
20
|
+
this.isSelected = value;
|
|
21
|
+
}
|
|
22
|
+
randomPositions(length) {
|
|
23
|
+
const points = [];
|
|
24
|
+
for (let i = 0; i < length; i++) {
|
|
25
|
+
const xr = Math.random() * 0.5 + 0.25;
|
|
26
|
+
const yr = Math.random() * 0.5 + 0.25;
|
|
27
|
+
const bounds = this.map.getBounds();
|
|
28
|
+
points.push([
|
|
29
|
+
(1 - xr) * bounds.getWest() + xr * bounds.getEast(),
|
|
30
|
+
(1 - yr) * bounds.getSouth() + yr * bounds.getNorth()
|
|
31
|
+
]);
|
|
32
|
+
}
|
|
33
|
+
return points;
|
|
34
|
+
}
|
|
35
|
+
delete() {
|
|
36
|
+
this.destroy();
|
|
37
|
+
this.manager.deleteElement(this);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { AbstractElement } from './abstract.js';
|
|
2
|
+
import type { GeometryManager } from '../geometry_manager.js';
|
|
3
|
+
import type { ElementPath, SelectionNode, SelectionNodeUpdater } from './types.js';
|
|
4
|
+
export declare abstract class AbstractPathElement extends AbstractElement {
|
|
5
|
+
path: ElementPath;
|
|
6
|
+
protected readonly isLine: boolean;
|
|
7
|
+
constructor(manager: GeometryManager, isLine: boolean);
|
|
8
|
+
protected handleDrag(e: maplibregl.MapMouseEvent): void;
|
|
9
|
+
getSelectionNodes(): SelectionNode[];
|
|
10
|
+
getSelectionNodeUpdater(properties?: Record<string, unknown>): SelectionNodeUpdater | undefined;
|
|
11
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { AbstractElement } from './abstract.js';
|
|
2
|
+
import { getMiddlePoint, lat2mercator, mercator2lat } from '../utils.js';
|
|
3
|
+
export class AbstractPathElement extends AbstractElement {
|
|
4
|
+
path = [];
|
|
5
|
+
isLine;
|
|
6
|
+
constructor(manager, isLine) {
|
|
7
|
+
super(manager);
|
|
8
|
+
this.isLine = isLine;
|
|
9
|
+
}
|
|
10
|
+
handleDrag(e) {
|
|
11
|
+
const { lng, lat } = e.lngLat;
|
|
12
|
+
let x0 = lng;
|
|
13
|
+
let y0 = lat2mercator(lat);
|
|
14
|
+
const moveHandler = (e) => {
|
|
15
|
+
const { lng, lat } = e.lngLat;
|
|
16
|
+
const y = lat2mercator(lat);
|
|
17
|
+
const dx = lng - x0;
|
|
18
|
+
const dy = y - y0;
|
|
19
|
+
y0 = y;
|
|
20
|
+
x0 = lng;
|
|
21
|
+
this.path = this.path.map(([x, y]) => [x + dx, mercator2lat(lat2mercator(y) + dy)]);
|
|
22
|
+
this.source.setData(this.getFeature(false));
|
|
23
|
+
this.manager.drawSelectionNodes();
|
|
24
|
+
e.preventDefault();
|
|
25
|
+
};
|
|
26
|
+
this.manager.map.on('mousemove', moveHandler);
|
|
27
|
+
this.manager.map.once('mouseup', () => this.manager.map.off('mousemove', moveHandler));
|
|
28
|
+
e.preventDefault();
|
|
29
|
+
}
|
|
30
|
+
getSelectionNodes() {
|
|
31
|
+
const points = [];
|
|
32
|
+
for (let i = 0; i < this.path.length; i++) {
|
|
33
|
+
points.push({ index: i, coordinates: this.path[i] });
|
|
34
|
+
if (this.isLine && i === this.path.length - 1)
|
|
35
|
+
continue;
|
|
36
|
+
const j = (i + 1) % this.path.length;
|
|
37
|
+
points.push({
|
|
38
|
+
index: i + 0.5,
|
|
39
|
+
transparent: true,
|
|
40
|
+
coordinates: getMiddlePoint(this.path[i], this.path[j])
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return points;
|
|
44
|
+
}
|
|
45
|
+
getSelectionNodeUpdater(properties) {
|
|
46
|
+
if (properties == undefined)
|
|
47
|
+
return;
|
|
48
|
+
const index = properties.index;
|
|
49
|
+
let point;
|
|
50
|
+
if (index % 1 === 0) {
|
|
51
|
+
point = this.path[index];
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
const i = Math.floor(index);
|
|
55
|
+
const j = (i + 1) % this.path.length;
|
|
56
|
+
point = getMiddlePoint(this.path[i], this.path[j]);
|
|
57
|
+
this.path.splice(j, 0, point);
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
update: (lng, lat) => {
|
|
61
|
+
point[0] = lng;
|
|
62
|
+
point[1] = lat;
|
|
63
|
+
this.source.setData(this.getFeature(false));
|
|
64
|
+
},
|
|
65
|
+
delete: () => {
|
|
66
|
+
if (this.isLine) {
|
|
67
|
+
if (this.path.length <= 2)
|
|
68
|
+
return this.delete();
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
if (this.path.length <= 3)
|
|
72
|
+
return this.delete();
|
|
73
|
+
}
|
|
74
|
+
this.path.splice(index, 1);
|
|
75
|
+
this.source.setData(this.getFeature(false));
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { GeometryManager } from '../geometry_manager.js';
|
|
2
|
+
import type { ElementPath } from './types.js';
|
|
3
|
+
import { MapLayerLine } from '../map_layer/line.js';
|
|
4
|
+
import { AbstractPathElement } from './abstract_path.js';
|
|
5
|
+
import type { StateObject } from '../state/types.js';
|
|
6
|
+
export declare class LineElement extends AbstractPathElement {
|
|
7
|
+
readonly layer: MapLayerLine;
|
|
8
|
+
readonly path: ElementPath;
|
|
9
|
+
constructor(manager: GeometryManager, line?: ElementPath);
|
|
10
|
+
select(value: boolean): void;
|
|
11
|
+
getFeature(includeProperties?: boolean): GeoJSON.Feature<GeoJSON.LineString>;
|
|
12
|
+
destroy(): void;
|
|
13
|
+
getState(): StateObject;
|
|
14
|
+
static fromState(manager: GeometryManager, state: StateObject): LineElement;
|
|
15
|
+
static fromGeoJSON(manager: GeometryManager, feature: GeoJSON.Feature<GeoJSON.LineString>): LineElement;
|
|
16
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { MapLayerLine } from '../map_layer/line.js';
|
|
2
|
+
import { AbstractPathElement } from './abstract_path.js';
|
|
3
|
+
export class LineElement extends AbstractPathElement {
|
|
4
|
+
layer;
|
|
5
|
+
path;
|
|
6
|
+
constructor(manager, line) {
|
|
7
|
+
super(manager, true);
|
|
8
|
+
this.path = line ?? this.randomPositions(2);
|
|
9
|
+
this.layer = new MapLayerLine(manager, 'line' + this.slug, this.sourceId);
|
|
10
|
+
this.layer.on('click', () => this.manager.selectElement(this));
|
|
11
|
+
this.layer.on('mousedown', (e) => {
|
|
12
|
+
if (!this.isSelected)
|
|
13
|
+
return;
|
|
14
|
+
if ('ignore' in e && e.ignore)
|
|
15
|
+
return;
|
|
16
|
+
this.handleDrag(e);
|
|
17
|
+
});
|
|
18
|
+
this.source.setData(this.getFeature());
|
|
19
|
+
}
|
|
20
|
+
select(value) {
|
|
21
|
+
super.select(value);
|
|
22
|
+
this.layer.isSelected = value;
|
|
23
|
+
}
|
|
24
|
+
getFeature(includeProperties = false) {
|
|
25
|
+
return {
|
|
26
|
+
type: 'Feature',
|
|
27
|
+
properties: includeProperties ? this.layer.getGeoJSONProperties() : {},
|
|
28
|
+
geometry: { type: 'LineString', coordinates: this.path }
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
destroy() {
|
|
32
|
+
this.layer.destroy();
|
|
33
|
+
this.map.removeSource(this.sourceId);
|
|
34
|
+
}
|
|
35
|
+
getState() {
|
|
36
|
+
return {
|
|
37
|
+
type: 'line',
|
|
38
|
+
points: this.path,
|
|
39
|
+
style: this.layer.getState()
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
static fromState(manager, state) {
|
|
43
|
+
const element = new LineElement(manager, state.points);
|
|
44
|
+
if (state.style)
|
|
45
|
+
element.layer.setState(state.style);
|
|
46
|
+
return element;
|
|
47
|
+
}
|
|
48
|
+
static fromGeoJSON(manager, feature) {
|
|
49
|
+
const element = new LineElement(manager, feature.geometry.coordinates);
|
|
50
|
+
element.layer.setGeoJSONProperties(feature.properties);
|
|
51
|
+
return element;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { AbstractElement } from './abstract.js';
|
|
2
|
+
import type { GeometryManager } from '../geometry_manager.js';
|
|
3
|
+
import type { ElementPoint, SelectionNode, SelectionNodeUpdater } from './types.js';
|
|
4
|
+
import { MapLayerSymbol } from '../map_layer/symbol.js';
|
|
5
|
+
import type { StateObject } from '../state/types.js';
|
|
6
|
+
export declare class MarkerElement extends AbstractElement {
|
|
7
|
+
readonly layer: MapLayerSymbol;
|
|
8
|
+
private point;
|
|
9
|
+
constructor(manager: GeometryManager, point?: ElementPoint);
|
|
10
|
+
select(value: boolean): void;
|
|
11
|
+
getFeature(includeProperties?: boolean): GeoJSON.Feature<GeoJSON.Point>;
|
|
12
|
+
getSelectionNodes(): SelectionNode[];
|
|
13
|
+
getSelectionNodeUpdater(): SelectionNodeUpdater | undefined;
|
|
14
|
+
destroy(): void;
|
|
15
|
+
getState(): StateObject;
|
|
16
|
+
static fromState(manager: GeometryManager, state: StateObject): MarkerElement;
|
|
17
|
+
static fromGeoJSON(manager: GeometryManager, feature: GeoJSON.Feature<GeoJSON.Point>): MarkerElement;
|
|
18
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { AbstractElement } from './abstract.js';
|
|
2
|
+
import { MapLayerSymbol } from '../map_layer/symbol.js';
|
|
3
|
+
export class MarkerElement extends AbstractElement {
|
|
4
|
+
layer;
|
|
5
|
+
point = [0, 0];
|
|
6
|
+
constructor(manager, point) {
|
|
7
|
+
super(manager);
|
|
8
|
+
this.point = point ?? this.randomPositions(1)[0];
|
|
9
|
+
this.layer = new MapLayerSymbol(manager, 'symbol' + this.slug, this.sourceId);
|
|
10
|
+
this.layer.on('click', () => this.manager.selectElement(this));
|
|
11
|
+
this.source.setData(this.getFeature());
|
|
12
|
+
}
|
|
13
|
+
select(value) {
|
|
14
|
+
super.select(value);
|
|
15
|
+
this.layer.isSelected = value;
|
|
16
|
+
}
|
|
17
|
+
getFeature(includeProperties = false) {
|
|
18
|
+
return {
|
|
19
|
+
type: 'Feature',
|
|
20
|
+
properties: includeProperties ? this.layer.getGeoJSONProperties() : {},
|
|
21
|
+
geometry: {
|
|
22
|
+
type: 'Point',
|
|
23
|
+
coordinates: this.point
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
getSelectionNodes() {
|
|
28
|
+
return [{ index: 0, coordinates: this.point }];
|
|
29
|
+
}
|
|
30
|
+
getSelectionNodeUpdater() {
|
|
31
|
+
return {
|
|
32
|
+
update: (lng, lat) => {
|
|
33
|
+
this.point[0] = lng;
|
|
34
|
+
this.point[1] = lat;
|
|
35
|
+
this.source.setData(this.getFeature());
|
|
36
|
+
},
|
|
37
|
+
delete: () => this.delete()
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
destroy() {
|
|
41
|
+
this.layer.destroy();
|
|
42
|
+
this.map.removeSource(this.sourceId);
|
|
43
|
+
}
|
|
44
|
+
getState() {
|
|
45
|
+
return {
|
|
46
|
+
type: 'marker',
|
|
47
|
+
point: this.point,
|
|
48
|
+
style: this.layer.getState()
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
static fromState(manager, state) {
|
|
52
|
+
const element = new MarkerElement(manager, state.point);
|
|
53
|
+
if (state.style)
|
|
54
|
+
element.layer.setState(state.style);
|
|
55
|
+
return element;
|
|
56
|
+
}
|
|
57
|
+
static fromGeoJSON(manager, feature) {
|
|
58
|
+
const element = new MarkerElement(manager, feature.geometry.coordinates);
|
|
59
|
+
element.layer.setGeoJSONProperties(feature.properties);
|
|
60
|
+
return element;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { GeometryManager } from '../geometry_manager.js';
|
|
2
|
+
import type { ElementPath } from './types.js';
|
|
3
|
+
import { MapLayerFill } from '../map_layer/fill.js';
|
|
4
|
+
import { MapLayerLine } from '../map_layer/line.js';
|
|
5
|
+
import { AbstractPathElement } from './abstract_path.js';
|
|
6
|
+
import type { StateObject } from '../state/types.js';
|
|
7
|
+
export declare class PolygonElement extends AbstractPathElement {
|
|
8
|
+
readonly fillLayer: MapLayerFill;
|
|
9
|
+
readonly strokeLayer: MapLayerLine;
|
|
10
|
+
constructor(manager: GeometryManager, polygon?: ElementPath);
|
|
11
|
+
select(value: boolean): void;
|
|
12
|
+
getFeature(includeProperties?: boolean): GeoJSON.Feature<GeoJSON.Polygon>;
|
|
13
|
+
destroy(): void;
|
|
14
|
+
getState(): StateObject;
|
|
15
|
+
static fromState(manager: GeometryManager, state: StateObject): PolygonElement;
|
|
16
|
+
static fromGeoJSON(manager: GeometryManager, feature: GeoJSON.Feature<GeoJSON.Polygon>): PolygonElement;
|
|
17
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { MapLayerFill } from '../map_layer/fill.js';
|
|
2
|
+
import { MapLayerLine } from '../map_layer/line.js';
|
|
3
|
+
import { AbstractPathElement } from './abstract_path.js';
|
|
4
|
+
export class PolygonElement extends AbstractPathElement {
|
|
5
|
+
fillLayer;
|
|
6
|
+
strokeLayer;
|
|
7
|
+
constructor(manager, polygon) {
|
|
8
|
+
super(manager, false);
|
|
9
|
+
this.path = polygon ?? this.randomPositions(3);
|
|
10
|
+
this.fillLayer = new MapLayerFill(manager, 'fill' + this.slug, this.sourceId);
|
|
11
|
+
this.fillLayer.on('click', () => this.manager.selectElement(this));
|
|
12
|
+
this.fillLayer.on('mousedown', (e) => {
|
|
13
|
+
if (!this.isSelected)
|
|
14
|
+
return;
|
|
15
|
+
this.handleDrag(e);
|
|
16
|
+
});
|
|
17
|
+
this.strokeLayer = new MapLayerLine(manager, 'line' + this.slug, this.sourceId);
|
|
18
|
+
this.strokeLayer.on('click', () => this.manager.selectElement(this));
|
|
19
|
+
this.source.setData(this.getFeature());
|
|
20
|
+
}
|
|
21
|
+
select(value) {
|
|
22
|
+
super.select(value);
|
|
23
|
+
this.fillLayer.isSelected = value;
|
|
24
|
+
this.strokeLayer.isSelected = value;
|
|
25
|
+
}
|
|
26
|
+
getFeature(includeProperties = false) {
|
|
27
|
+
return {
|
|
28
|
+
type: 'Feature',
|
|
29
|
+
properties: includeProperties
|
|
30
|
+
? { ...this.fillLayer.getGeoJSONProperties(), ...this.strokeLayer.getGeoJSONProperties() }
|
|
31
|
+
: {},
|
|
32
|
+
geometry: { type: 'Polygon', coordinates: [[...this.path, this.path[0]]] }
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
destroy() {
|
|
36
|
+
this.fillLayer.destroy();
|
|
37
|
+
this.strokeLayer.destroy();
|
|
38
|
+
this.map.removeSource(this.sourceId);
|
|
39
|
+
}
|
|
40
|
+
getState() {
|
|
41
|
+
return {
|
|
42
|
+
type: 'polygon',
|
|
43
|
+
points: this.path,
|
|
44
|
+
style: this.fillLayer.getState(),
|
|
45
|
+
strokeStyle: this.strokeLayer.getState()
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
static fromState(manager, state) {
|
|
49
|
+
const element = new PolygonElement(manager, state.points);
|
|
50
|
+
if (state.style)
|
|
51
|
+
element.fillLayer.setState(state.style);
|
|
52
|
+
if (state.strokeStyle)
|
|
53
|
+
element.strokeLayer.setState(state.strokeStyle);
|
|
54
|
+
return element;
|
|
55
|
+
}
|
|
56
|
+
static fromGeoJSON(manager, feature) {
|
|
57
|
+
const coordinates = feature.geometry.coordinates[0].slice(0, -1);
|
|
58
|
+
const element = new PolygonElement(manager, coordinates);
|
|
59
|
+
element.fillLayer.setGeoJSONProperties(feature.properties);
|
|
60
|
+
element.strokeLayer.setGeoJSONProperties(feature.properties);
|
|
61
|
+
return element;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type ElementPoint = [number, number];
|
|
2
|
+
export type ElementPath = ElementPoint[];
|
|
3
|
+
export interface SelectionNode {
|
|
4
|
+
coordinates: ElementPoint;
|
|
5
|
+
index: number;
|
|
6
|
+
transparent?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface SelectionNodeUpdater {
|
|
9
|
+
update: (lng: number, lat: number) => void;
|
|
10
|
+
delete: () => void;
|
|
11
|
+
}
|
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
import { type Writable } from 'svelte/store';
|
|
2
|
-
import type { AbstractElement } from './
|
|
3
|
-
import
|
|
2
|
+
import type { AbstractElement } from './element/abstract.js';
|
|
3
|
+
import { Cursor } from './cursor.js';
|
|
4
|
+
import type { StateObject } from './state/types.js';
|
|
5
|
+
import { SymbolLibrary } from './symbols.js';
|
|
4
6
|
export declare class GeometryManager {
|
|
5
7
|
readonly elements: Writable<AbstractElement[]>;
|
|
6
8
|
readonly map: maplibregl.Map;
|
|
7
|
-
readonly
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
readonly selectedElement: Writable<AbstractElement | undefined>;
|
|
10
|
+
readonly canvas: HTMLElement;
|
|
11
|
+
readonly cursor: Cursor;
|
|
12
|
+
readonly symbolLibrary: SymbolLibrary;
|
|
13
|
+
private readonly selectionNodes;
|
|
10
14
|
constructor(map: maplibregl.Map);
|
|
11
|
-
|
|
12
|
-
|
|
15
|
+
selectElement(element: AbstractElement | undefined): void;
|
|
16
|
+
drawSelectionNodes(): void;
|
|
17
|
+
getState(): StateObject;
|
|
18
|
+
saveState(): Promise<void>;
|
|
19
|
+
loadState(hash: string): Promise<void>;
|
|
13
20
|
getElement(index: number): AbstractElement;
|
|
14
|
-
|
|
15
|
-
|
|
21
|
+
addNewMarker(): AbstractElement;
|
|
22
|
+
addNewLine(): AbstractElement;
|
|
23
|
+
addNewPolygon(): AbstractElement;
|
|
16
24
|
private addElement;
|
|
17
|
-
|
|
25
|
+
deleteElement(element: AbstractElement): void;
|
|
26
|
+
getGeoJSON(): GeoJSON.FeatureCollection;
|
|
27
|
+
addGeoJSON(geojson: GeoJSON.FeatureCollection): void;
|
|
18
28
|
}
|