@versatiles/svelte 1.1.1 → 2.0.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.
Files changed (53) hide show
  1. package/dist/components/BBoxMap/AutoComplete.svelte +0 -1
  2. package/dist/components/BBoxMap/BBoxMap.svelte +1 -2
  3. package/dist/{utils/draw → components/BBoxMap/lib}/bbox.d.ts +1 -2
  4. package/dist/components/BasicMap/BasicMap.svelte +7 -9
  5. package/dist/components/BasicMap/BasicMap.svelte.d.ts +5 -4
  6. package/dist/components/LocatorMap/LocatorMap.svelte +0 -2
  7. package/dist/components/MapEditor/MapEditor.svelte +16 -3
  8. package/dist/components/MapEditor/components/Editor.svelte +46 -39
  9. package/dist/components/MapEditor/components/Editor.svelte.d.ts +1 -1
  10. package/dist/components/MapEditor/components/EditorFill.svelte +7 -9
  11. package/dist/components/MapEditor/components/EditorStroke.svelte +9 -11
  12. package/dist/components/MapEditor/components/EditorSymbol.svelte +23 -19
  13. package/dist/components/MapEditor/components/InputRow.svelte +34 -0
  14. package/dist/components/MapEditor/components/InputRow.svelte.d.ts +9 -0
  15. package/dist/components/MapEditor/components/Sidebar.svelte +116 -111
  16. package/dist/components/MapEditor/components/SidebarPanel.svelte +92 -0
  17. package/dist/components/MapEditor/components/SidebarPanel.svelte.d.ts +10 -0
  18. package/dist/components/MapEditor/components/SymbolSelector.svelte +7 -15
  19. package/dist/components/MapEditor/lib/element/abstract.d.ts +3 -3
  20. package/dist/components/MapEditor/lib/element/abstract.js +1 -1
  21. package/dist/components/MapEditor/lib/element/line.d.ts +3 -4
  22. package/dist/components/MapEditor/lib/element/line.js +0 -1
  23. package/dist/components/MapEditor/lib/element/marker.d.ts +4 -4
  24. package/dist/components/MapEditor/lib/element/polygon.d.ts +3 -3
  25. package/dist/components/MapEditor/lib/geometry_manager.d.ts +20 -10
  26. package/dist/components/MapEditor/lib/geometry_manager.js +46 -52
  27. package/dist/components/MapEditor/lib/map_layer/abstract.d.ts +4 -3
  28. package/dist/components/MapEditor/lib/map_layer/abstract.js +30 -12
  29. package/dist/components/MapEditor/lib/map_layer/fill.d.ts +4 -3
  30. package/dist/components/MapEditor/lib/map_layer/fill.js +9 -8
  31. package/dist/components/MapEditor/lib/map_layer/line.d.ts +4 -3
  32. package/dist/components/MapEditor/lib/map_layer/line.js +15 -14
  33. package/dist/components/MapEditor/lib/map_layer/symbol.d.ts +21 -10
  34. package/dist/components/MapEditor/lib/map_layer/symbol.js +72 -31
  35. package/dist/components/MapEditor/lib/state/constants.d.ts +4 -0
  36. package/dist/components/MapEditor/lib/state/constants.js +22 -0
  37. package/dist/components/MapEditor/lib/state/manager.d.ts +16 -0
  38. package/dist/components/MapEditor/lib/state/manager.js +76 -0
  39. package/dist/components/MapEditor/lib/state/reader.d.ts +21 -14
  40. package/dist/components/MapEditor/lib/state/reader.js +259 -139
  41. package/dist/components/MapEditor/lib/state/types.d.ts +28 -12
  42. package/dist/components/MapEditor/lib/state/writer.d.ts +18 -14
  43. package/dist/components/MapEditor/lib/state/writer.js +183 -156
  44. package/dist/components/MapEditor/lib/utils.d.ts +2 -5
  45. package/dist/components/MapEditor/lib/utils.js +0 -19
  46. package/package.json +28 -27
  47. package/dist/components/MapEditor/lib/__mocks__/cursor.d.ts +0 -5
  48. package/dist/components/MapEditor/lib/__mocks__/cursor.js +0 -6
  49. package/dist/components/MapEditor/lib/__mocks__/geometry_manager.d.ts +0 -22
  50. package/dist/components/MapEditor/lib/__mocks__/geometry_manager.js +0 -21
  51. package/dist/components/MapEditor/lib/__mocks__/map.d.ts +0 -36
  52. package/dist/components/MapEditor/lib/__mocks__/map.js +0 -26
  53. /package/dist/{utils/draw → components/BBoxMap/lib}/bbox.js +0 -0
@@ -3,9 +3,8 @@ import { MarkerElement } from './element/marker.js';
3
3
  import { LineElement } from './element/line.js';
4
4
  import { PolygonElement } from './element/polygon.js';
5
5
  import { Cursor } from './cursor.js';
6
- import { StateWriter } from './state/writer.js';
7
- import { StateReader } from './state/reader.js';
8
6
  import { SymbolLibrary } from './symbols.js';
7
+ import { StateManager } from './state/manager.js';
9
8
  export class GeometryManager {
10
9
  elements;
11
10
  map;
@@ -13,6 +12,7 @@ export class GeometryManager {
13
12
  canvas;
14
13
  cursor;
15
14
  symbolLibrary;
15
+ state;
16
16
  selectionNodes;
17
17
  constructor(map) {
18
18
  this.elements = writable([]);
@@ -53,7 +53,6 @@ export class GeometryManager {
53
53
  if (e.originalEvent.shiftKey) {
54
54
  selectedNode.delete();
55
55
  this.drawSelectionNodes();
56
- this.saveState();
57
56
  }
58
57
  else {
59
58
  const onMove = (e) => {
@@ -63,8 +62,8 @@ export class GeometryManager {
63
62
  };
64
63
  map.on('mousemove', onMove);
65
64
  map.once('mouseup', () => {
66
- this.saveState();
67
65
  map.off('mousemove', onMove);
66
+ this.state.log();
68
67
  });
69
68
  }
70
69
  });
@@ -79,12 +78,11 @@ export class GeometryManager {
79
78
  this.selectElement(undefined);
80
79
  e.preventDefault();
81
80
  });
82
- map.on('moveend', () => this.saveState());
83
- const hash = location.hash.slice(1);
84
- if (hash)
85
- this.loadState(hash);
81
+ this.state = new StateManager(this);
86
82
  }
87
83
  selectElement(element) {
84
+ if (element == get(this.selectedElement))
85
+ return;
88
86
  const elements = get(this.elements);
89
87
  elements.forEach((e) => e.select(e == element));
90
88
  this.selectedElement.set(element);
@@ -105,48 +103,42 @@ export class GeometryManager {
105
103
  const center = this.map.getCenter();
106
104
  return {
107
105
  map: {
108
- point: [center.lng, center.lat],
106
+ center: [center.lng, center.lat],
109
107
  zoom: this.map.getZoom()
110
108
  },
111
109
  elements: get(this.elements).map((element) => element.getState())
112
110
  };
113
111
  }
114
- async saveState() {
115
- const writer = new StateWriter();
116
- writer.writeObject(this.getState());
117
- location.hash = await writer.getBase64compressed();
118
- }
119
- async loadState(hash) {
120
- if (!hash)
112
+ setState(state) {
113
+ if (!state)
121
114
  return;
122
- try {
123
- const reader = await StateReader.fromBase64compressed(hash);
124
- const state = reader.readObject();
125
- if (!state)
126
- return;
127
- if (state.map?.zoom)
115
+ this.selectElement(undefined);
116
+ this.elements.update((elements) => {
117
+ elements.forEach((e) => e.destroy());
118
+ return [];
119
+ });
120
+ if (state.map) {
121
+ if (state.map.zoom)
128
122
  this.map.setZoom(state.map.zoom);
129
- if (state.map?.point) {
130
- this.map.setCenter({ lng: state.map.point[0], lat: state.map.point[1] });
131
- }
132
- if (state.elements) {
133
- const elements = state.elements.map((element) => {
134
- switch (element.type) {
135
- case 'marker':
136
- return MarkerElement.fromState(this, element);
137
- case 'line':
138
- return LineElement.fromState(this, element);
139
- case 'polygon':
140
- return PolygonElement.fromState(this, element);
141
- default:
142
- throw new Error('Unknown element type');
143
- }
144
- });
145
- this.elements.set(elements);
123
+ if (state.map.center) {
124
+ const [lng, lat] = state.map.center;
125
+ this.map.setCenter({ lng, lat });
146
126
  }
147
127
  }
148
- catch (error) {
149
- console.error(error);
128
+ if (state.elements) {
129
+ const elements = 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
+ this.elements.set(elements);
150
142
  }
151
143
  }
152
144
  getElement(index) {
@@ -154,28 +146,31 @@ export class GeometryManager {
154
146
  }
155
147
  addNewMarker() {
156
148
  const element = new MarkerElement(this);
157
- this.addElement(element);
149
+ this.appendElement(element);
150
+ this.selectElement(element);
158
151
  return element;
159
152
  }
160
153
  addNewLine() {
161
154
  const element = new LineElement(this);
162
- this.addElement(element);
155
+ this.appendElement(element);
156
+ this.selectElement(element);
163
157
  return element;
164
158
  }
165
159
  addNewPolygon() {
166
160
  const element = new PolygonElement(this);
167
- this.addElement(element);
161
+ this.appendElement(element);
162
+ this.selectElement(element);
168
163
  return element;
169
164
  }
170
- addElement(element) {
165
+ appendElement(element) {
171
166
  this.elements.update((elements) => [...elements, element]);
172
- this.saveState();
167
+ this.state.log();
173
168
  }
174
- deleteElement(element) {
175
- this.elements.update((elements) => elements.filter((e) => e !== element));
169
+ removeElement(element) {
176
170
  if (get(this.selectedElement) === element)
177
171
  this.selectElement(undefined);
178
- this.saveState();
172
+ this.elements.update((elements) => elements.filter((e) => e !== element));
173
+ this.state.log();
179
174
  }
180
175
  getGeoJSON() {
181
176
  const center = this.map.getCenter();
@@ -189,7 +184,7 @@ export class GeometryManager {
189
184
  };
190
185
  }
191
186
  addGeoJSON(geojson) {
192
- if ('map' in geojson) {
187
+ if ('map' in geojson && geojson.map) {
193
188
  const { map } = geojson;
194
189
  if (typeof map.zoom === 'number') {
195
190
  this.map.setZoom(map.zoom);
@@ -216,8 +211,7 @@ export class GeometryManager {
216
211
  default:
217
212
  throw new Error(`Unknown geometry type "${feature.geometry.type}"`);
218
213
  }
219
- this.addElement(element);
214
+ this.appendElement(element);
220
215
  }
221
- this.saveState();
222
216
  }
223
217
  }
@@ -1,6 +1,6 @@
1
1
  import type { LayerFill, LayerLine, LayerSymbol } from './types.js';
2
2
  import type { GeometryManager } from '../geometry_manager.js';
3
- import type { StateObject } from '../state/types.js';
3
+ import type { StateStyle } from '../state/types.js';
4
4
  type LayerSpec = LayerFill | LayerLine | LayerSymbol;
5
5
  type Events = 'click' | 'mousedown' | 'mousemove' | 'mouseup';
6
6
  type MouseEventHandler = (event: maplibregl.MapMouseEvent) => void;
@@ -13,6 +13,7 @@ export declare abstract class MapLayer<T extends LayerSpec> {
13
13
  eventHandlers: Map<Events, MouseEventHandler[]>;
14
14
  isSelected: boolean;
15
15
  constructor(manager: GeometryManager, id: string);
16
+ pushState(): void;
16
17
  addLayer(source: string, type: 'symbol' | 'line' | 'fill', layout: T['layout'], paint: T['paint']): void;
17
18
  on(event: Events, handler: MouseEventHandler): void;
18
19
  off(event: Events, handler: MouseEventHandler): void;
@@ -20,10 +21,10 @@ export declare abstract class MapLayer<T extends LayerSpec> {
20
21
  private addEvents;
21
22
  setPaint(paint: T['paint']): void;
22
23
  updatePaint<K extends keyof T['paint'], V extends T['paint'][K]>(key: K, value: V): void;
23
- setLayout(layout: T['layout']): void;
24
+ updateLayout(obj: T['layout']): void;
24
25
  updateLayout<K extends keyof T['layout'], V extends T['layout'][K]>(key: K, value: V): void;
25
26
  destroy(): void;
26
- abstract getState(): StateObject | undefined;
27
+ abstract getState(): StateStyle | undefined;
27
28
  abstract getGeoJSONProperties(): GeoJSON.GeoJsonProperties;
28
29
  abstract setGeoJSONProperties(properties: GeoJSON.GeoJsonProperties): void;
29
30
  }
@@ -12,11 +12,24 @@ export class MapLayer {
12
12
  this.map = manager.map;
13
13
  this.id = id;
14
14
  }
15
+ pushState() {
16
+ this.manager.state.log();
17
+ }
15
18
  addLayer(source, type, layout, paint) {
19
+ layout = cloneClean(layout);
20
+ paint = cloneClean(paint);
16
21
  this.layout = layout;
17
22
  this.paint = paint;
18
23
  this.map.addLayer({ id: this.id, source, type, layout, paint }, 'selection_nodes');
19
24
  this.addEvents();
25
+ function cloneClean(obj) {
26
+ const clone = { ...obj };
27
+ for (const key in clone) {
28
+ if (clone[key] == null)
29
+ delete clone[key];
30
+ }
31
+ return clone;
32
+ }
20
33
  }
21
34
  on(event, handler) {
22
35
  if (!this.eventHandlers.has(event))
@@ -75,18 +88,23 @@ export class MapLayer {
75
88
  this.map.setPaintProperty(this.id, key, value);
76
89
  this.paint[key] = value;
77
90
  }
78
- setLayout(layout) {
79
- if (layout === undefined)
80
- return;
81
- const keys = new Set(Object.keys(layout).concat(Object.keys(this.layout)));
82
- for (const key of keys.values())
83
- this.updateLayout(key, layout[key]);
84
- }
85
- updateLayout(key, value) {
86
- if (this.layout[key] == value)
87
- return;
88
- this.map.setLayoutProperty(this.id, key, value);
89
- this.layout[key] = value;
91
+ updateLayout(arg1, arg2) {
92
+ if (typeof arg1 === 'string') {
93
+ if (this.layout[arg1] == arg2)
94
+ return;
95
+ this.map.setLayoutProperty(this.id, arg1, arg2);
96
+ if (arg2 == null) {
97
+ delete this.layout[arg1];
98
+ }
99
+ else {
100
+ this.layout[arg1] = arg2;
101
+ }
102
+ }
103
+ else if (typeof arg1 === 'object') {
104
+ for (const [key, value] of Object.entries(arg1)) {
105
+ this.updateLayout(key, value);
106
+ }
107
+ }
90
108
  }
91
109
  destroy() {
92
110
  this.map.removeLayer(this.id);
@@ -1,7 +1,7 @@
1
1
  import type { LayerFill } from './types.js';
2
2
  import { MapLayer } from './abstract.js';
3
3
  import type { GeometryManager } from '../geometry_manager.js';
4
- import type { StateObject } from '../state/types.js';
4
+ import type { StateStyle } from '../state/types.js';
5
5
  interface Fill {
6
6
  xf: number;
7
7
  yf: number;
@@ -15,9 +15,10 @@ export declare class MapLayerFill extends MapLayer<LayerFill> {
15
15
  color: import("svelte/store").Writable<string>;
16
16
  opacity: import("svelte/store").Writable<number>;
17
17
  pattern: import("svelte/store").Writable<number>;
18
+ static readonly defaultStyle: StateStyle;
18
19
  constructor(manager: GeometryManager, id: string, source: string);
19
- getState(): StateObject | undefined;
20
- setState(state: StateObject): void;
20
+ getState(): StateStyle | undefined;
21
+ setState(state: StateStyle): void;
21
22
  getGeoJSONProperties(): GeoJSON.GeoJsonProperties;
22
23
  setGeoJSONProperties(properties: GeoJSON.GeoJsonProperties): void;
23
24
  }
@@ -12,6 +12,11 @@ export class MapLayerFill extends MapLayer {
12
12
  color = writable('#ff0000');
13
13
  opacity = writable(1);
14
14
  pattern = writable(0);
15
+ static defaultStyle = {
16
+ color: '#ff0000',
17
+ opacity: 1,
18
+ pattern: 0
19
+ };
15
20
  constructor(manager, id, source) {
16
21
  super(manager, id);
17
22
  this.addLayer(source, 'fill', {}, {
@@ -49,15 +54,15 @@ export class MapLayerFill extends MapLayer {
49
54
  };
50
55
  this.color.subscribe(() => {
51
56
  updatePattern();
52
- this.manager.saveState();
57
+ this.manager.state.log();
53
58
  });
54
59
  this.pattern.subscribe(() => {
55
60
  updatePattern();
56
- this.manager.saveState();
61
+ this.manager.state.log();
57
62
  });
58
63
  this.opacity.subscribe((value) => {
59
64
  this.updatePaint('fill-opacity', value);
60
- this.manager.saveState();
65
+ this.manager.state.log();
61
66
  });
62
67
  }
63
68
  getState() {
@@ -65,11 +70,7 @@ export class MapLayerFill extends MapLayer {
65
70
  color: get(this.color),
66
71
  opacity: get(this.opacity),
67
72
  pattern: get(this.pattern)
68
- }, {
69
- color: '#ff0000',
70
- opacity: 1,
71
- pattern: 0
72
- });
73
+ }, MapLayerFill.defaultStyle);
73
74
  }
74
75
  setState(state) {
75
76
  if (state.color)
@@ -1,20 +1,21 @@
1
1
  import type { LayerLine } from './types.js';
2
2
  import { MapLayer } from './abstract.js';
3
3
  import type { GeometryManager } from '../geometry_manager.js';
4
- import type { StateObject } from '../state/types.js';
4
+ import type { StateStyle } from '../state/types.js';
5
5
  export declare const dashArrays: Map<number, {
6
6
  name: string;
7
7
  array: number[] | undefined;
8
8
  }>;
9
9
  export declare class MapLayerLine extends MapLayer<LayerLine> {
10
+ static readonly defaultStyle: StateStyle;
10
11
  color: import("svelte/store").Writable<string>;
11
12
  dashed: import("svelte/store").Writable<number>;
12
13
  visible: import("svelte/store").Writable<boolean>;
13
14
  width: import("svelte/store").Writable<number>;
14
15
  dashArray: import("svelte/store").Readable<number[]>;
15
16
  constructor(manager: GeometryManager, id: string, source: string);
16
- getState(): StateObject | undefined;
17
- setState(state: StateObject): void;
17
+ getState(): StateStyle | undefined;
18
+ setState(state: StateStyle): void;
18
19
  getGeoJSONProperties(): GeoJSON.GeoJsonProperties;
19
20
  setGeoJSONProperties(properties: GeoJSON.GeoJsonProperties): void;
20
21
  }
@@ -8,10 +8,16 @@ export const dashArrays = new Map([
8
8
  [2, { name: 'dotted', array: [0, 2] }]
9
9
  ]);
10
10
  export class MapLayerLine extends MapLayer {
11
- color = writable('#ff0000');
12
- dashed = writable(0);
13
- visible = writable(true);
14
- width = writable(2);
11
+ static defaultStyle = {
12
+ color: '#ff0000',
13
+ pattern: 0,
14
+ visible: true,
15
+ width: 2
16
+ };
17
+ color = writable(MapLayerLine.defaultStyle.color);
18
+ dashed = writable(MapLayerLine.defaultStyle.pattern);
19
+ visible = writable(MapLayerLine.defaultStyle.visible);
20
+ width = writable(MapLayerLine.defaultStyle.width);
15
21
  dashArray = derived(this.dashed, (dashed) => dashArrays.get(dashed)?.array ?? [100]);
16
22
  constructor(manager, id, source) {
17
23
  super(manager, id);
@@ -26,19 +32,19 @@ export class MapLayerLine extends MapLayer {
26
32
  });
27
33
  this.color.subscribe((v) => {
28
34
  this.updatePaint('line-color', Color.parse(v));
29
- this.manager.saveState();
35
+ this.manager.state.log();
30
36
  });
31
37
  this.dashArray.subscribe((v) => {
32
38
  this.updatePaint('line-dasharray', v);
33
- this.manager.saveState();
39
+ this.manager.state.log();
34
40
  });
35
41
  this.visible.subscribe((v) => {
36
42
  this.updateLayout('visibility', v ? 'visible' : 'none');
37
- this.manager.saveState();
43
+ this.manager.state.log();
38
44
  });
39
45
  this.width.subscribe((v) => {
40
46
  this.updatePaint('line-width', v);
41
- this.manager.saveState();
47
+ this.manager.state.log();
42
48
  });
43
49
  }
44
50
  getState() {
@@ -47,12 +53,7 @@ export class MapLayerLine extends MapLayer {
47
53
  pattern: get(this.dashed),
48
54
  visible: get(this.visible),
49
55
  width: get(this.width)
50
- }, {
51
- color: '#ff0000',
52
- pattern: 0,
53
- visible: true,
54
- width: 2
55
- });
56
+ }, MapLayerLine.defaultStyle);
56
57
  }
57
58
  setState(state) {
58
59
  if (state.color)
@@ -1,19 +1,30 @@
1
+ import { type Writable } from 'svelte/store';
1
2
  import type { LayerSymbol } from './types.js';
2
3
  import { MapLayer } from './abstract.js';
3
4
  import type { GeometryManager } from '../geometry_manager.js';
4
- import type { StateObject } from '../state/types.js';
5
+ import type { StateStyle } from '../state/types.js';
6
+ interface LabelAlign {
7
+ index: 0 | 1 | 2 | 3 | 4;
8
+ name: string;
9
+ anchor?: 'center' | 'left' | 'right' | 'bottom' | 'top';
10
+ }
11
+ export declare const labelPositions: LabelAlign[];
5
12
  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
+ static readonly defaultStyle: StateStyle;
14
+ color: Writable<string>;
15
+ halo: Writable<number>;
16
+ rotate: Writable<number>;
17
+ size: Writable<number>;
18
+ symbolIndex: Writable<number>;
19
+ label: Writable<string>;
20
+ labelAlign: Writable<number>;
13
21
  symbolInfo: import("svelte/store").Readable<import("../symbols.js").SymbolInfo>;
22
+ textAnchor: import("svelte/store").Readable<"center" | "top" | "bottom" | "right" | "left" | undefined>;
23
+ textVariableAnchor: import("svelte/store").Readable<("center" | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "top" | "bottom" | "right" | "left")[] | undefined>;
14
24
  constructor(manager: GeometryManager, id: string, source: string);
15
- getState(): StateObject | undefined;
16
- setState(state: StateObject): void;
25
+ getState(): StateStyle | undefined;
26
+ setState(state: StateStyle): void;
17
27
  getGeoJSONProperties(): GeoJSON.GeoJsonProperties;
18
28
  setGeoJSONProperties(properties: GeoJSON.GeoJsonProperties): void;
19
29
  }
30
+ export {};
@@ -3,53 +3,75 @@ import { MapLayer } from './abstract.js';
3
3
  import { Color } from '@versatiles/style';
4
4
  import { getSymbol, getSymbolIndexByName } from '../symbols.js';
5
5
  import { removeDefaultFields } from '../utils.js';
6
- const defaultStyle = {
7
- color: '#ff0000',
8
- rotate: 0,
9
- size: 1,
10
- halo: 1,
11
- pattern: 38,
12
- label: ''
13
- };
6
+ export const labelPositions = [
7
+ { index: 0, name: 'auto' },
8
+ { index: 1, name: 'right', anchor: 'left' },
9
+ { index: 2, name: 'left', anchor: 'right' },
10
+ { index: 3, name: 'top', anchor: 'bottom' },
11
+ { index: 4, name: 'bottom', anchor: 'top' }
12
+ ];
14
13
  export class MapLayerSymbol extends MapLayer {
15
- color = writable(defaultStyle.color);
16
- halo = writable(defaultStyle.halo);
17
- rotate = writable(defaultStyle.rotate);
18
- size = writable(defaultStyle.size);
19
- symbolIndex = writable(defaultStyle.pattern);
20
- label = writable(defaultStyle.label);
21
- haloWidth = derived([this.halo, this.size], ([halo, size]) => halo * size);
14
+ static defaultStyle = {
15
+ color: '#ff0000',
16
+ rotate: 0,
17
+ size: 1,
18
+ halo: 1,
19
+ pattern: 38,
20
+ label: '',
21
+ align: 0
22
+ };
23
+ color = writable(MapLayerSymbol.defaultStyle.color);
24
+ halo = writable(MapLayerSymbol.defaultStyle.halo);
25
+ rotate = writable(MapLayerSymbol.defaultStyle.rotate);
26
+ size = writable(MapLayerSymbol.defaultStyle.size);
27
+ symbolIndex = writable(MapLayerSymbol.defaultStyle.pattern);
28
+ label = writable(MapLayerSymbol.defaultStyle.label);
29
+ labelAlign = writable(MapLayerSymbol.defaultStyle.align);
22
30
  symbolInfo = derived(this.symbolIndex, (index) => getSymbol(index));
31
+ textAnchor = derived(this.labelAlign, (index) => {
32
+ return lookupLabelAlign(index).anchor;
33
+ });
34
+ textVariableAnchor = derived([this.labelAlign, this.symbolInfo], ([index, symbol]) => {
35
+ if (index !== 0)
36
+ return undefined;
37
+ if (symbol.image == null) {
38
+ return ['center', 'left', 'right', 'top', 'bottom'];
39
+ }
40
+ return ['left', 'right', 'top', 'bottom'];
41
+ });
23
42
  constructor(manager, id, source) {
24
43
  super(manager, id);
25
44
  this.addLayer(source, 'symbol', {
26
45
  'icon-image': get(this.symbolInfo).image,
27
46
  'icon-offset': get(this.symbolInfo).offset,
28
- 'icon-overlap': 'always',
29
- 'icon-rotate': defaultStyle.rotate,
30
- 'icon-size': defaultStyle.size,
31
- 'text-field': defaultStyle.label,
47
+ 'icon-allow-overlap': true,
48
+ 'icon-rotate': get(this.rotate),
49
+ 'icon-size': get(this.size),
50
+ 'text-field': get(this.label),
32
51
  'text-font': ['noto_sans_regular'],
33
52
  'text-justify': 'left',
34
- 'text-optional': true,
35
- 'text-offset': [0.7, 0.7],
36
- 'text-variable-anchor': ['right', 'left', 'top', 'bottom']
53
+ 'text-overlap': 'always',
54
+ 'text-radial-offset': 0.7,
55
+ 'text-variable-anchor': get(this.textVariableAnchor),
56
+ 'text-anchor': get(this.textAnchor)
37
57
  }, {
38
- 'icon-color': defaultStyle.color,
58
+ 'icon-color': get(this.color),
39
59
  'icon-halo-blur': 0,
40
60
  'icon-halo-color': '#FFFFFF',
41
- 'icon-halo-width': defaultStyle.halo,
61
+ 'icon-halo-width': get(this.halo),
42
62
  'icon-opacity': 1,
43
63
  'text-halo-blur': 0,
44
64
  'text-halo-color': '#FFFFFF',
45
- 'text-halo-width': defaultStyle.halo
65
+ 'text-halo-width': get(this.halo)
46
66
  });
47
67
  this.color.subscribe((v) => this.updatePaint('icon-color', Color.parse(v)));
48
- this.haloWidth.subscribe((v) => {
68
+ this.halo.subscribe((v) => {
49
69
  this.updatePaint('icon-halo-width', v);
50
70
  this.updatePaint('text-halo-width', v);
51
71
  });
52
72
  this.label.subscribe((v) => this.updateLayout('text-field', v));
73
+ this.textAnchor.subscribe((v) => this.updateLayout('text-anchor', v));
74
+ this.textVariableAnchor.subscribe((v) => this.updateLayout('text-variable-anchor', v));
53
75
  this.rotate.subscribe((v) => this.updateLayout('icon-rotate', v));
54
76
  this.size.subscribe((v) => {
55
77
  this.updateLayout('icon-size', v);
@@ -58,11 +80,9 @@ export class MapLayerSymbol extends MapLayer {
58
80
  this.symbolInfo.subscribe((v) => {
59
81
  if (v.image == null) {
60
82
  this.updateLayout('icon-image', undefined);
61
- this.updateLayout('text-variable-anchor', ['center']);
62
83
  }
63
84
  else {
64
85
  this.updateLayout('icon-image', v.image);
65
- this.updateLayout('text-variable-anchor', ['right', 'left', 'top', 'bottom']);
66
86
  this.updateLayout('icon-offset', v.offset);
67
87
  }
68
88
  });
@@ -74,8 +94,9 @@ export class MapLayerSymbol extends MapLayer {
74
94
  size: get(this.size),
75
95
  halo: get(this.halo),
76
96
  pattern: get(this.symbolIndex),
77
- label: get(this.label)
78
- }, defaultStyle);
97
+ label: get(this.label),
98
+ align: get(this.labelAlign)
99
+ }, MapLayerSymbol.defaultStyle);
79
100
  }
80
101
  setState(state) {
81
102
  if (state.color)
@@ -90,6 +111,8 @@ export class MapLayerSymbol extends MapLayer {
90
111
  this.symbolIndex.set(state.pattern);
91
112
  if (state.label)
92
113
  this.label.set(state.label);
114
+ if (state.align)
115
+ this.labelAlign.set(lookupLabelAlign(state.align).index);
93
116
  }
94
117
  getGeoJSONProperties() {
95
118
  return {
@@ -98,7 +121,8 @@ export class MapLayerSymbol extends MapLayer {
98
121
  'symbol-rotate': get(this.rotate),
99
122
  'symbol-size': get(this.size),
100
123
  'symbol-pattern': get(this.symbolInfo).name,
101
- 'symbol-label': get(this.label)
124
+ 'symbol-label': get(this.label),
125
+ 'symbol-label-align': lookupLabelAlign(this.labelAlign).name
102
126
  };
103
127
  }
104
128
  setGeoJSONProperties(properties) {
@@ -114,6 +138,8 @@ export class MapLayerSymbol extends MapLayer {
114
138
  this.size.set(properties['symbol-size']);
115
139
  if (properties['symbol-label'])
116
140
  this.label.set(properties['symbol-label']);
141
+ if (properties['symbol-label-align'])
142
+ this.labelAlign.set(lookupLabelAlign(properties['symbol-label-align']).index);
117
143
  if (properties['symbol-pattern']) {
118
144
  const index = getSymbolIndexByName(properties['symbol-pattern']);
119
145
  if (index != null)
@@ -121,3 +147,18 @@ export class MapLayerSymbol extends MapLayer {
121
147
  }
122
148
  }
123
149
  }
150
+ function lookupLabelAlign(index) {
151
+ let pos;
152
+ if (typeof index === 'object') {
153
+ index = get(index);
154
+ }
155
+ if (typeof index === 'number') {
156
+ pos = labelPositions.find((p) => p.index === index);
157
+ }
158
+ else if (typeof index === 'string') {
159
+ pos = labelPositions.find((p) => p.name === index);
160
+ }
161
+ if (pos == null)
162
+ return labelPositions[0];
163
+ return pos;
164
+ }
@@ -0,0 +1,4 @@
1
+ export declare const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
2
+ export declare const BASE64_CODE2BITS: [boolean, boolean, boolean, boolean, boolean, boolean][];
3
+ export declare const CHAR_VALUE2CODE: number[];
4
+ export declare const CHAR_CODE2VALUE: number[];