-
-
Notifications
You must be signed in to change notification settings - Fork 640
/
source.ts
186 lines (175 loc) · 6.54 KB
/
source.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
import {VectorTileSource} from '../source/vector_tile_source';
import {RasterTileSource} from '../source/raster_tile_source';
import {RasterDEMTileSource} from '../source/raster_dem_tile_source';
import {GeoJSONSource} from '../source/geojson_source';
import {VideoSource} from '../source/video_source';
import {ImageSource} from '../source/image_source';
import {CanvasSource} from '../source/canvas_source';
import {Dispatcher} from '../util/dispatcher';
import type {SourceSpecification} from '@maplibre/maplibre-gl-style-spec';
import type {Event, Evented} from '../util/evented';
import type {Map} from '../ui/map';
import type {Tile} from './tile';
import type {OverscaledTileID, CanonicalTileID} from './tile_id';
import type {CanvasSourceSpecification} from '../source/canvas_source';
const registeredSources = {} as {[key:string]: SourceClass};
/**
* The `Source` interface must be implemented by each source type, including "core" types (`vector`, `raster`,
* `video`, etc.) and all custom, third-party types.
*
* **Event** `data` - Fired with `{dataType: 'source', sourceDataType: 'metadata'}` to indicate that any necessary metadata
* has been loaded so that it's okay to call `loadTile`; and with `{dataType: 'source', sourceDataType: 'content'}`
* to indicate that the source data has changed, so that any current caches should be flushed.
*
* @group Sources
*/
export interface Source {
readonly type: string;
/**
* The id for the source. Must not be used by any existing source.
*/
id: string;
/**
* The minimum zoom level for the source.
*/
minzoom: number;
/**
* The maximum zoom level for the source.
*/
maxzoom: number;
/**
* The tile size for the source.
*/
tileSize: number;
/**
* The attribution for the source.
*/
attribution?: string;
/**
* `true` if zoom levels are rounded to the nearest integer in the source data, `false` if they are floor-ed to the nearest integer.
*/
roundZoom?: boolean;
/**
* `false` if tiles can be drawn outside their boundaries, `true` if they cannot.
*/
isTileClipped?: boolean;
tileID?: CanonicalTileID;
/**
* `true` if tiles should be sent back to the worker for each overzoomed zoom level, `false` if not.
*/
reparseOverscaled?: boolean;
vectorLayerIds?: Array<string>;
/**
* True if the source has transiotion, false otherwise.
*/
hasTransition(): boolean;
/**
* True if the source is loaded, false otherwise.
*/
loaded(): boolean;
/**
* An ability to fire an event to all the listeners, see {@link Evented}
* @param event - The event to fire
*/
fire(event: Event): unknown;
/**
* This method is called when the source is added to the map.
* @param map - The map instance
*/
onAdd?(map: Map): void;
/**
* This method is called when the source is removed from the map.
* @param map - The map instance
*/
onRemove?(map: Map): void;
/**
* This method does the heavy lifting of loading a tile.
* In most cases it will defer the work to the relevant worker source.
* @param tile - The tile to load
*/
loadTile(tile: Tile): Promise<void>;
/**
* True is the tile is part of the source, false otherwise.
* @param tileID - The tile ID
*/
hasTile?(tileID: OverscaledTileID): boolean;
/**
* Allows to abort a tile loading.
* @param tile - The tile to abort
*/
abortTile?(tile: Tile): Promise<void>;
/**
* Allows to unload a tile.
* @param tile - The tile to unload
*/
unloadTile?(tile: Tile): Promise<void>;
/**
* @returns A plain (stringifiable) JS object representing the current state of the source.
* Creating a source using the returned object as the `options` should result in a Source that is
* equivalent to this one.
*/
serialize(): any;
/**
* Allows to execute a prepare step before the source is used.
*/
prepare?(): void;
}
/**
* A general definition of a {@link Source} class for factory usage
*/
export type SourceClass = {
new (id: string, specification: SourceSpecification | CanvasSourceSpecification, dispatcher: Dispatcher, eventedParent: Evented): Source;
}
/**
* Creates a tiled data source instance given an options object.
*
* @param id - The id for the source. Must not be used by any existing source.
* @param specification - Source options, specific to the source type (except for `options.type`, which is always required).
* @param source - A source definition object compliant with
* [`maplibre-gl-style-spec`](https://maplibre.org/maplibre-style-spec/#sources) or, for a third-party source type,
* with that type's requirements.
* @param dispatcher - A {@link Dispatcher} instance, which can be used to send messages to the workers.
* @returns a newly created source
*/
export const create = (id: string, specification: SourceSpecification | CanvasSourceSpecification, dispatcher: Dispatcher, eventedParent: Evented): Source => {
const Class = getSourceType(specification.type);
const source = new Class(id, specification, dispatcher, eventedParent);
if (source.id !== id) {
throw new Error(`Expected Source id to be ${id} instead of ${source.id}`);
}
return source;
};
const getSourceType = (name: string): SourceClass => {
switch (name) {
case 'geojson':
return GeoJSONSource;
case 'image':
return ImageSource;
case 'raster':
return RasterTileSource;
case 'raster-dem':
return RasterDEMTileSource;
case 'vector':
return VectorTileSource;
case 'video':
return VideoSource;
case 'canvas':
return CanvasSource;
}
return registeredSources[name];
};
const setSourceType = (name: string, type: SourceClass) => {
registeredSources[name] = type;
};
/**
* Adds a custom source type, making it available for use with {@link Map#addSource}.
* @param name - The name of the source type; source definition objects use this name in the `{type: ...}` field.
* @param sourceType - A {@link SourceClass} - which is a constructor for the `Source` interface.
* @returns a promise that is resolved when the source type is ready or rejected with an error.
*/
export const addSourceType = async (name: string, SourceType: SourceClass): Promise<void> => {
if (getSourceType(name)) {
throw new Error(`A source type called "${name}" already exists.`);
}
setSourceType(name, SourceType);
};