@superrouteca/smap-openlayers 0.0.0-stage → 1.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/CHANGELOG.md +13 -0
- package/LICENSE +21 -0
- package/README.md +148 -2
- package/examples/index.html +97 -0
- package/package.json +67 -4
- package/src/common/access.js +198 -0
- package/src/common/badge.js +56 -0
- package/src/common/embed.js +166 -0
- package/src/index.js +326 -0
- package/src/on-smap.js +273 -0
- package/types/index.d.ts +183 -0
- package/types/on-smap.d.ts +31 -0
package/src/on-smap.js
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
// @superrouteca/smap-openlayers/on-smap — OpenLayers sources and layers on an sMap map, through the sMap map's own
|
|
2
|
+
// calls (addRasterLayer, addWmsLayer, addWmtsLayer, addVectorTiles, addData / addPoints / addLines / addPolygons):
|
|
3
|
+
//
|
|
4
|
+
// import { addOpenLayersLayer } from '@superrouteca/smap-openlayers/on-smap';
|
|
5
|
+
// addOpenLayersLayer(smapMap, 'radar', new TileLayer({ source: new TileWMS({ url, params: { LAYERS: 'radar' } }) }));
|
|
6
|
+
//
|
|
7
|
+
// Tiles: XYZ (and OSM, TileImage, TileJSON), TileWMS / ImageWMS, WMTS, VectorTile (with Style Specification layers,
|
|
8
|
+
// as OpenLayers style functions have no counterpart). Features: a Vector source (GeoJSON written in WGS 84; a layer's
|
|
9
|
+
// fixed Style becomes the colours). A layer without `slot` / `before` draws on top in the order added, as in 1.0.
|
|
10
|
+
|
|
11
|
+
/** `{a-c}` and `{0-3}` ranges of OpenLayers URL templates, expanded; `{-y}` becomes `{y}` (TMS). */
|
|
12
|
+
export function expandTemplates(urls) {
|
|
13
|
+
const out = [];
|
|
14
|
+
(urls || []).forEach(function (u) {
|
|
15
|
+
const m = /\{([a-z0-9])-([a-z0-9])\}/i.exec(u);
|
|
16
|
+
if (!m) { out.push(u); return; }
|
|
17
|
+
const a = m[1].charCodeAt(0);
|
|
18
|
+
const b = m[2].charCodeAt(0);
|
|
19
|
+
for (let c = a; c <= b; c++) { out.push.apply(out, expandTemplates([u.replace(m[0], String.fromCharCode(c))])); }
|
|
20
|
+
});
|
|
21
|
+
return out.map(function (u) { return u.replace(/\{-y\}/g, '{y}'); });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function attributionOf(source) {
|
|
25
|
+
const a = source && source.getAttributions && source.getAttributions();
|
|
26
|
+
if (!a) { return undefined; }
|
|
27
|
+
let v = a;
|
|
28
|
+
if (typeof a === 'function') {
|
|
29
|
+
try { v = a({ viewState: { projection: null, resolution: 1, center: [0, 0], zoom: 0, rotation: 0 }, extent: null }); } catch (e) { v = null; }
|
|
30
|
+
}
|
|
31
|
+
if (Array.isArray(v)) { return v.join(' ') || undefined; }
|
|
32
|
+
return v || undefined;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function placement(options) {
|
|
36
|
+
const p = {};
|
|
37
|
+
if (options.slot) { p.slot = options.slot; }
|
|
38
|
+
if (options.before) { p.before = options.before; }
|
|
39
|
+
if (options.zIndex !== undefined) { p.zIndex = options.zIndex; }
|
|
40
|
+
return p;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function zoomRange(layer, out) {
|
|
44
|
+
// OpenLayers zoom levels are one above the sMap map's (256 against 512 px tiles).
|
|
45
|
+
if (layer && typeof layer.getMinZoom === 'function') {
|
|
46
|
+
const min = layer.getMinZoom();
|
|
47
|
+
const max = layer.getMaxZoom();
|
|
48
|
+
if (isFinite(min) && min > -Infinity) { out.minzoom = Math.max(0, min - 1); }
|
|
49
|
+
if (isFinite(max) && max < Infinity) { out.maxzoom = Math.max(0, max - 1); }
|
|
50
|
+
}
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function need(smap, name) {
|
|
55
|
+
if (typeof smap[name] !== 'function') { throw new Error('sMap: this needs @superrouteca/smap 1.1.0 (' + name + ')'); }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** What kind of OpenLayers source this is, by what it can do (works across copies of OpenLayers). */
|
|
59
|
+
export function sourceKind(source) {
|
|
60
|
+
if (!source) { return null; }
|
|
61
|
+
if (typeof source.getParams === 'function') { return 'wms'; }
|
|
62
|
+
if (typeof source.getMatrixSet === 'function' && typeof source.getRequestEncoding === 'function') { return 'wmts'; }
|
|
63
|
+
if (typeof source.getSourceTiles === 'function' || typeof source.getFeaturesInExtent === 'function' && typeof source.getTileGrid === 'function') { return 'vectortile'; }
|
|
64
|
+
if (typeof source.getFeatures === 'function' && typeof source.addFeature === 'function') { return 'vector'; }
|
|
65
|
+
if (typeof source.getUrls === 'function' && typeof source.getTileGrid === 'function') { return 'xyz'; }
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** A WMTS source as an XYZ template when its matrix set is Web Mercator with matrices by zoom; null otherwise. */
|
|
70
|
+
export function wmtsTemplate(source) {
|
|
71
|
+
const grid = source.getTileGrid && source.getTileGrid();
|
|
72
|
+
const ids = grid && grid.getMatrixIds ? grid.getMatrixIds() : null;
|
|
73
|
+
const proj = source.getProjection && source.getProjection();
|
|
74
|
+
const code = proj && proj.getCode ? proj.getCode() : '';
|
|
75
|
+
if (!ids || !ids.length || !/3857|900913|GoogleMapsCompatible/i.test(code + ' ' + source.getMatrixSet())) { return null; }
|
|
76
|
+
// Matrix ids are the zoom, perhaps after a common prefix ("EPSG:3857:5").
|
|
77
|
+
const m = /^(.*?)(\d+)$/.exec(ids[0]);
|
|
78
|
+
if (!m) { return null; }
|
|
79
|
+
const prefix = m[1];
|
|
80
|
+
const zoom0 = parseInt(m[2], 10);
|
|
81
|
+
const byZoom = ids.every(function (id, i) { return id === prefix + (zoom0 + i); });
|
|
82
|
+
if (!byZoom || zoom0 !== 0) { return null; }
|
|
83
|
+
const dims = source.getDimensions ? source.getDimensions() : {};
|
|
84
|
+
const style = source.getStyle ? source.getStyle() : '';
|
|
85
|
+
const urls = source.getUrls() || [];
|
|
86
|
+
if (!urls.length) { return null; }
|
|
87
|
+
const tm = prefix + '{z}';
|
|
88
|
+
if (source.getRequestEncoding() === 'REST') {
|
|
89
|
+
return urls.map(function (u) {
|
|
90
|
+
let t = u.replace(/\{Layer\}/g, source.getLayer()).replace(/\{TileMatrixSet\}/g, source.getMatrixSet()).replace(/\{Style\}/g, style)
|
|
91
|
+
.replace(/\{TileMatrix\}/g, tm).replace(/\{TileRow\}/g, '{y}').replace(/\{TileCol\}/g, '{x}');
|
|
92
|
+
Object.keys(dims).forEach(function (k) { t = t.replace(new RegExp('\\{' + k + '\\}', 'g'), String(dims[k])); });
|
|
93
|
+
return t;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return urls.map(function (u) {
|
|
97
|
+
const q = ['SERVICE=WMTS', 'REQUEST=GetTile', 'VERSION=' + (source.getVersion ? source.getVersion() : '1.0.0'),
|
|
98
|
+
'LAYER=' + encodeURIComponent(source.getLayer()), 'STYLE=' + encodeURIComponent(style), 'FORMAT=' + encodeURIComponent(source.getFormat()),
|
|
99
|
+
'TILEMATRIXSET=' + encodeURIComponent(source.getMatrixSet()), 'TILEMATRIX=' + tm, 'TILEROW={y}', 'TILECOL={x}'];
|
|
100
|
+
Object.keys(dims).forEach(function (k) { q.push(encodeURIComponent(k) + '=' + encodeURIComponent(dims[k])); });
|
|
101
|
+
return u + (u.indexOf('?') >= 0 ? '&' : '?') + q.join('&');
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function colorOf(c) {
|
|
106
|
+
if (c == null) { return undefined; }
|
|
107
|
+
if (Array.isArray(c)) { return 'rgba(' + c[0] + ', ' + c[1] + ', ' + c[2] + ', ' + (c[3] === undefined ? 1 : c[3]) + ')'; }
|
|
108
|
+
return typeof c === 'string' ? c : undefined;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** A layer's fixed OpenLayers Style (not a function) as sMap point, line and area options. */
|
|
112
|
+
export function styleOptions(style) {
|
|
113
|
+
const s = Array.isArray(style) ? style[0] : style;
|
|
114
|
+
if (!s || typeof s === 'function' || typeof s.getFill !== 'function') { return {}; }
|
|
115
|
+
const fill = s.getFill() && colorOf(s.getFill().getColor());
|
|
116
|
+
const stroke = s.getStroke();
|
|
117
|
+
const strokeColor = stroke && colorOf(stroke.getColor());
|
|
118
|
+
const strokeWidth = stroke && stroke.getWidth();
|
|
119
|
+
const image = s.getImage && s.getImage();
|
|
120
|
+
const out = { points: {}, lines: {}, polygons: {} };
|
|
121
|
+
if (strokeColor) { out.lines.color = strokeColor; out.polygons.outline = strokeColor; }
|
|
122
|
+
if (strokeWidth) { out.lines.width = strokeWidth; out.polygons.outlineWidth = strokeWidth; }
|
|
123
|
+
if (stroke && stroke.getLineDash && stroke.getLineDash() && strokeWidth) { out.lines.dash = stroke.getLineDash().map(function (d) { return d / strokeWidth; }); }
|
|
124
|
+
if (fill) { out.polygons.fill = fill; out.polygons.opacity = 1; }
|
|
125
|
+
if (image && typeof image.getRadius === 'function') {
|
|
126
|
+
out.points.radius = image.getRadius();
|
|
127
|
+
const f = image.getFill && image.getFill();
|
|
128
|
+
const st = image.getStroke && image.getStroke();
|
|
129
|
+
if (f) { out.points.color = colorOf(f.getColor()); }
|
|
130
|
+
if (st) { out.points.strokeColor = colorOf(st.getColor()); out.points.strokeWidth = st.getWidth(); }
|
|
131
|
+
} else if (image && typeof image.getSrc === 'function' && image.getSrc()) {
|
|
132
|
+
out.points.icon = image.getSrc();
|
|
133
|
+
if (image.getScale) { out.points.iconSize = image.getScale(); }
|
|
134
|
+
}
|
|
135
|
+
return out;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function geometryKind(type) {
|
|
139
|
+
if (type === 'Point' || type === 'MultiPoint') { return 'points'; }
|
|
140
|
+
if (type === 'LineString' || type === 'MultiLineString') { return 'lines'; }
|
|
141
|
+
return 'polygons';
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Adds an OpenLayers layer or source to an sMap map; resolves to the ids it added (one per kind of geometry for a
|
|
146
|
+
* vector source: `<id>`, `<id>:lines`, `<id>:areas`, as addData names them).
|
|
147
|
+
*
|
|
148
|
+
* @param {Object} smap an sMap map (after `await map.ready`)
|
|
149
|
+
* @param {string} id
|
|
150
|
+
* @param {Object} layerOrSource an OpenLayers layer (its source, opacity and zoom range are used) or source
|
|
151
|
+
* @param {Object} [options] slot, before, zIndex; `layers` (Style Specification layers) for a vector tile source;
|
|
152
|
+
* `projection` of a vector source's features (default the source's, else EPSG:3857);
|
|
153
|
+
* `GeoJSON` (ol/format/GeoJSON) to write them; and sMap layer options for features
|
|
154
|
+
*/
|
|
155
|
+
export async function addOpenLayersLayer(smap, id, layerOrSource, options) {
|
|
156
|
+
const o = Object.assign({}, options);
|
|
157
|
+
const isLayer = layerOrSource && typeof layerOrSource.getSource === 'function' && typeof layerOrSource.getOpacity === 'function';
|
|
158
|
+
const layer = isLayer ? layerOrSource : null;
|
|
159
|
+
const source = isLayer ? layerOrSource.getSource() : layerOrSource;
|
|
160
|
+
const kind = sourceKind(source);
|
|
161
|
+
const place = placement(o);
|
|
162
|
+
const credit = attributionOf(source);
|
|
163
|
+
const opacity = layer && layer.getOpacity() !== 1 ? layer.getOpacity() : undefined;
|
|
164
|
+
const common = zoomRange(layer, Object.assign({}, place));
|
|
165
|
+
if (credit) { common.attribution = credit; }
|
|
166
|
+
if (opacity !== undefined) { common.opacity = opacity; }
|
|
167
|
+
|
|
168
|
+
if (kind === 'wms') {
|
|
169
|
+
need(smap, 'addWmsLayer');
|
|
170
|
+
const p = Object.assign({}, source.getParams());
|
|
171
|
+
const url = (source.getUrls && source.getUrls() && source.getUrls()[0]) || (source.getUrl && source.getUrl());
|
|
172
|
+
const spec = Object.assign({}, common, { url: url, layers: p.LAYERS });
|
|
173
|
+
if (p.STYLES !== undefined) { spec.styles = p.STYLES; }
|
|
174
|
+
if (p.FORMAT !== undefined) { spec.format = p.FORMAT; }
|
|
175
|
+
if (p.TRANSPARENT !== undefined) { spec.transparent = String(p.TRANSPARENT) !== 'false'; }
|
|
176
|
+
if (p.VERSION === '1.1.1' || p.VERSION === '1.3.0') { spec.version = p.VERSION; }
|
|
177
|
+
const extra = {};
|
|
178
|
+
Object.keys(p).forEach(function (k) { if (['LAYERS', 'STYLES', 'FORMAT', 'TRANSPARENT', 'VERSION'].indexOf(k) < 0) { extra[k] = p[k]; } });
|
|
179
|
+
if (Object.keys(extra).length) { spec.params = extra; }
|
|
180
|
+
smap.addWmsLayer(id, spec);
|
|
181
|
+
return [id];
|
|
182
|
+
}
|
|
183
|
+
if (kind === 'wmts') {
|
|
184
|
+
const tiles = wmtsTemplate(source);
|
|
185
|
+
if (tiles) {
|
|
186
|
+
need(smap, 'addRasterLayer');
|
|
187
|
+
const grid = source.getTileGrid();
|
|
188
|
+
const size = grid.getTileSize(0);
|
|
189
|
+
smap.addRasterLayer(id, Object.assign({}, common, { tiles: tiles, tileSize: Array.isArray(size) ? size[0] : size }));
|
|
190
|
+
return [id];
|
|
191
|
+
}
|
|
192
|
+
need(smap, 'addWmtsLayer');
|
|
193
|
+
const urls = source.getUrls() || [];
|
|
194
|
+
await smap.addWmtsLayer(id, Object.assign({}, common, {
|
|
195
|
+
url: urls[0], layer: source.getLayer(), tileMatrixSet: source.getMatrixSet(), style: source.getStyle(), format: source.getFormat(),
|
|
196
|
+
encoding: source.getRequestEncoding() === 'REST' ? 'rest' : 'kvp',
|
|
197
|
+
}));
|
|
198
|
+
return [id];
|
|
199
|
+
}
|
|
200
|
+
if (kind === 'vectortile') {
|
|
201
|
+
need(smap, 'addVectorTiles');
|
|
202
|
+
if (!Array.isArray(o.layers) || !o.layers.length) {
|
|
203
|
+
throw new Error('sMap: a vector tile source needs `layers` (Style Specification layers): OpenLayers style functions have no counterpart');
|
|
204
|
+
}
|
|
205
|
+
const spec = Object.assign({}, place, { tiles: expandTemplates(source.getUrls() || []), layers: o.layers });
|
|
206
|
+
if (credit) { spec.attribution = credit; }
|
|
207
|
+
if (common.minzoom !== undefined) { spec.minzoom = common.minzoom; }
|
|
208
|
+
if (common.maxzoom !== undefined) { spec.maxzoom = common.maxzoom; }
|
|
209
|
+
smap.addVectorTiles(id, spec);
|
|
210
|
+
return [id];
|
|
211
|
+
}
|
|
212
|
+
if (kind === 'xyz') {
|
|
213
|
+
need(smap, 'addRasterLayer');
|
|
214
|
+
const raw = source.getUrls() || [];
|
|
215
|
+
if (!raw.length) { throw new Error('sMap: this tile source has no URL template'); }
|
|
216
|
+
const grid = source.getTileGrid();
|
|
217
|
+
const size = grid ? grid.getTileSize(0) : 256;
|
|
218
|
+
const spec = Object.assign({}, common, { tiles: expandTemplates(raw), tileSize: Array.isArray(size) ? size[0] : size });
|
|
219
|
+
if (raw.some(function (u) { return u.indexOf('{-y}') >= 0; })) { spec.scheme = 'tms'; }
|
|
220
|
+
smap.addRasterLayer(id, spec);
|
|
221
|
+
return [id];
|
|
222
|
+
}
|
|
223
|
+
if (kind === 'vector') {
|
|
224
|
+
const GeoJSONFormat = o.GeoJSON || (await import('ol/format/GeoJSON.js')).default;
|
|
225
|
+
const projection = o.projection || (source.getProjection && source.getProjection()) || 'EPSG:3857';
|
|
226
|
+
const fc = new GeoJSONFormat().writeFeaturesObject(source.getFeatures(), { featureProjection: projection, dataProjection: 'EPSG:4326' });
|
|
227
|
+
const look = layer && typeof layer.getStyle === 'function' ? styleOptions(layer.getStyle()) : {};
|
|
228
|
+
const layerOptions = pick(o, ['layers', 'projection', 'GeoJSON', 'slot', 'before', 'zIndex']);
|
|
229
|
+
const kinds = { points: [], lines: [], polygons: [] };
|
|
230
|
+
fc.features.forEach(function (f) { if (f.geometry) { kinds[geometryKind(f.geometry.type)].push(f); } });
|
|
231
|
+
const ids = [];
|
|
232
|
+
const names = { points: id, lines: id + ':lines', polygons: id + ':areas' };
|
|
233
|
+
const calls = { points: 'addPoints', lines: 'addLines', polygons: 'addPolygons' };
|
|
234
|
+
Object.keys(kinds).forEach(function (k) {
|
|
235
|
+
if (!kinds[k].length) { return; }
|
|
236
|
+
smap[calls[k]](names[k], { type: 'FeatureCollection', features: kinds[k] }, Object.assign({}, look[k] || {}, layerOptions, place));
|
|
237
|
+
ids.push(names[k]);
|
|
238
|
+
});
|
|
239
|
+
return ids;
|
|
240
|
+
}
|
|
241
|
+
throw new Error('sMap: this OpenLayers source has no counterpart on an sMap map (XYZ, OSM, TileJSON, TileWMS, ImageWMS, WMTS, VectorTile and Vector sources are)');
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function pick(o, skip) {
|
|
245
|
+
const out = {};
|
|
246
|
+
Object.keys(o || {}).forEach(function (k) { if (skip.indexOf(k) < 0) { out[k] = o[k]; } });
|
|
247
|
+
return out;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Adds every layer of an OpenLayers map (or a list of layers) to an sMap map, in their order, as `<prefix><n>`;
|
|
252
|
+
* resolves to { added: [ids], skipped: [{ index, reason }] }.
|
|
253
|
+
*/
|
|
254
|
+
export async function addOpenLayersLayers(smap, layers, options) {
|
|
255
|
+
const o = Object.assign({ prefix: 'ol-' }, options);
|
|
256
|
+
const list = layers && typeof layers.getLayers === 'function' ? layers.getLayers().getArray() : (layers && layers.getArray ? layers.getArray() : layers || []);
|
|
257
|
+
const added = [];
|
|
258
|
+
const skipped = [];
|
|
259
|
+
for (let i = 0; i < list.length; i++) {
|
|
260
|
+
const l = list[i];
|
|
261
|
+
if (typeof l.getLayers === 'function' && !l.getSource) {
|
|
262
|
+
const inner = await addOpenLayersLayers(smap, l, Object.assign({}, o, { prefix: o.prefix + i + '-' }));
|
|
263
|
+
added.push.apply(added, inner.added);
|
|
264
|
+
skipped.push.apply(skipped, inner.skipped);
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
// An sMap basemap already in the OpenLayers map is the sMap map itself.
|
|
268
|
+
if (typeof l.getSMap === 'function' || (l.get && l.get('smap:skip'))) { continue; }
|
|
269
|
+
try { added.push.apply(added, await addOpenLayersLayer(smap, o.prefix + i, l, o.layerOptions && o.layerOptions[i])); }
|
|
270
|
+
catch (e) { skipped.push({ index: i, reason: e.message }); }
|
|
271
|
+
}
|
|
272
|
+
return { added: added, skipped: skipped };
|
|
273
|
+
}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// Types of @superrouteca/smap-openlayers.
|
|
2
|
+
import Layer from 'ol/layer/Layer.js';
|
|
3
|
+
import TileLayer from 'ol/layer/Tile.js';
|
|
4
|
+
import XYZ from 'ol/source/XYZ.js';
|
|
5
|
+
import Control from 'ol/control/Control.js';
|
|
6
|
+
import type { Options as XYZOptions } from 'ol/source/XYZ.js';
|
|
7
|
+
import type { Map as SMapMap, MapOptions as SMapMapOptions, StyleFlavor } from '@superrouteca/smap';
|
|
8
|
+
import type SMapClient from '@superrouteca/smap/client';
|
|
9
|
+
|
|
10
|
+
export type { StyleFlavor };
|
|
11
|
+
/** A colour scheme or a saved custom style (`custom:<id>`). */
|
|
12
|
+
export type SMapStyle = StyleFlavor | `custom:${string}`;
|
|
13
|
+
|
|
14
|
+
/** How the adapters reach the service: a map key or a token (renewed through getToken), the nearest node. */
|
|
15
|
+
export interface AccessOptions {
|
|
16
|
+
/** The map service, `https://tile.srsr.ca` by default. */
|
|
17
|
+
baseUrl?: string;
|
|
18
|
+
/** A map key (`smk_…`) whose allowlist names this site. */
|
|
19
|
+
apiKey?: string;
|
|
20
|
+
token?: string;
|
|
21
|
+
/** Called at start and again two minutes before each token expires. */
|
|
22
|
+
getToken?: () => string | Promise<string>;
|
|
23
|
+
/** Node URLs known in advance, used while `baseUrl` is down. */
|
|
24
|
+
nodes?: string[];
|
|
25
|
+
/** Read from the nearest node (default true). */
|
|
26
|
+
nearest?: boolean;
|
|
27
|
+
fetch?: typeof fetch;
|
|
28
|
+
timeoutMs?: number;
|
|
29
|
+
/** A JS client of your own instead of the options above. */
|
|
30
|
+
client?: SMapClient;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** The service access the raster layer uses (token, node order, failover). */
|
|
34
|
+
export declare class SMapAccess {
|
|
35
|
+
constructor(options?: AccessOptions);
|
|
36
|
+
readonly client: SMapClient;
|
|
37
|
+
readonly baseUrl: string;
|
|
38
|
+
start(): Promise<this>;
|
|
39
|
+
refresh(): Promise<string | null>;
|
|
40
|
+
token(): string | null;
|
|
41
|
+
nodes(): string[];
|
|
42
|
+
head(): string;
|
|
43
|
+
isOurs(url: string): boolean;
|
|
44
|
+
headers(url: string): Record<string, string>;
|
|
45
|
+
rewrite(url: string): string;
|
|
46
|
+
failed(url: string): void;
|
|
47
|
+
withKey(path: string): string;
|
|
48
|
+
style(style: SMapStyle, language?: string): Promise<Record<string, unknown>>;
|
|
49
|
+
rasterTile(style: SMapStyle, z: number, x: number, y: number, options?: { lang?: string; retina?: boolean }): Promise<Blob>;
|
|
50
|
+
rasterTemplate(style: SMapStyle, options?: { lang?: string; retina?: boolean }): string;
|
|
51
|
+
on(listener: (type: 'token' | 'nodes', value: unknown) => void): this;
|
|
52
|
+
stop(): void;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface SMapLayerOptions extends Omit<SMapMapOptions, 'container' | 'style'> {
|
|
56
|
+
/** A colour scheme, `custom:<id>`, or a style URL or object of your own. */
|
|
57
|
+
style?: SMapStyle | string | Record<string, unknown>;
|
|
58
|
+
/** OpenLayers' clicks and pointer moves reach sMap's layers (popups, Auto Zoom, onClick, hover); default true. */
|
|
59
|
+
interactive?: boolean;
|
|
60
|
+
/** The sMap Web SDK module to use (default the installed `@superrouteca/smap`). */
|
|
61
|
+
sdk?: unknown;
|
|
62
|
+
className?: string;
|
|
63
|
+
opacity?: number;
|
|
64
|
+
visible?: boolean;
|
|
65
|
+
extent?: number[];
|
|
66
|
+
zIndex?: number;
|
|
67
|
+
minResolution?: number;
|
|
68
|
+
maxResolution?: number;
|
|
69
|
+
minZoom?: number;
|
|
70
|
+
maxZoom?: number;
|
|
71
|
+
properties?: Record<string, unknown>;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** The sMap vector map as an OpenLayers layer (Web Mercator views). The sMap map's calls are forwarded once it is ready. */
|
|
75
|
+
export declare class SMapLayer extends Layer {
|
|
76
|
+
constructor(options?: SMapLayerOptions);
|
|
77
|
+
/** Resolves to the sMap map once it is ready. */
|
|
78
|
+
readonly ready: Promise<SMapMap>;
|
|
79
|
+
/** The sMap map, or null before it is ready. */
|
|
80
|
+
getSMap(): SMapMap | null;
|
|
81
|
+
/** An sMap map call whose answer is a value (e.g. `call('basemap')`, `call('toJSON')`). */
|
|
82
|
+
call<T = unknown>(name: string, ...args: unknown[]): Promise<T>;
|
|
83
|
+
setStyle(style: SMapStyle | string | Record<string, unknown>): this;
|
|
84
|
+
setLanguage(language: string): this;
|
|
85
|
+
setBasemap(overrides: Record<string, Record<string, unknown>>): this;
|
|
86
|
+
setAutoZoom(on: boolean): this;
|
|
87
|
+
addPoints(id: string, data: unknown, options?: Record<string, unknown>): this;
|
|
88
|
+
addLines(id: string, data: unknown, options?: Record<string, unknown>): this;
|
|
89
|
+
addPolygons(id: string, data: unknown, options?: Record<string, unknown>): this;
|
|
90
|
+
addData(id: string, input: unknown, options?: Record<string, unknown>): this;
|
|
91
|
+
setData(id: string, data: unknown): this;
|
|
92
|
+
/** The sMap map's setVisible (the layer's own setVisible stays OpenLayers'). */
|
|
93
|
+
setSMapVisible(id: string, visible: boolean): this;
|
|
94
|
+
fitLayer(id: string, options?: Record<string, unknown>): this;
|
|
95
|
+
openPopup(lngLat: [number, number] | { lng: number; lat: number }, content: unknown, options?: Record<string, unknown>): this;
|
|
96
|
+
closePopup(): this;
|
|
97
|
+
setBuildings3D(on: boolean, options?: { color?: string; opacity?: number }): this;
|
|
98
|
+
addSource(id: string, source: Record<string, unknown>): this;
|
|
99
|
+
removeSource(id: string): this;
|
|
100
|
+
addStyleLayer(layer: Record<string, unknown>, options?: { before?: string; slot?: 'bottom' | 'roads' | 'labels' | 'top' }): this;
|
|
101
|
+
setPaint(layerId: string, name: string, value: unknown): this;
|
|
102
|
+
setLayout(layerId: string, name: string, value: unknown): this;
|
|
103
|
+
setFilter(layerId: string, filter: unknown): this;
|
|
104
|
+
addRasterLayer(id: string, options: Record<string, unknown>): this;
|
|
105
|
+
addWmsLayer(id: string, options: Record<string, unknown>): this;
|
|
106
|
+
addWmtsLayer(id: string, options: Record<string, unknown>): this;
|
|
107
|
+
addVectorTiles(id: string, options: Record<string, unknown>): this;
|
|
108
|
+
addArcGisLayer(id: string, options: Record<string, unknown>): this;
|
|
109
|
+
loadLayers(json: unknown): this;
|
|
110
|
+
/** Removes one of the sMap map's layers. */
|
|
111
|
+
removeSMapLayer(id: string): this;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface SMapRasterSourceOptions extends AccessOptions, Omit<XYZOptions, 'url' | 'urls' | 'tileSize' | 'tilePixelRatio' | 'tileLoadFunction'> {
|
|
115
|
+
style?: SMapStyle;
|
|
116
|
+
language?: string;
|
|
117
|
+
/** 512 px tiles for high-density screens (default: the screen's pixel ratio above 1). */
|
|
118
|
+
retina?: boolean;
|
|
119
|
+
/** An access of your own, shared between sources. */
|
|
120
|
+
access?: SMapAccess;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** sMap raster tiles as an OpenLayers XYZ source. */
|
|
124
|
+
export declare class SMapRasterSource extends XYZ {
|
|
125
|
+
constructor(options?: SMapRasterSourceOptions);
|
|
126
|
+
setStyle(style: SMapStyle): this;
|
|
127
|
+
setLanguage(language: string): this;
|
|
128
|
+
getAccess(): SMapAccess;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface SMapRasterLayerOptions extends SMapRasterSourceOptions {
|
|
132
|
+
source?: SMapRasterSource;
|
|
133
|
+
className?: string;
|
|
134
|
+
opacity?: number;
|
|
135
|
+
visible?: boolean;
|
|
136
|
+
zIndex?: number;
|
|
137
|
+
minZoom?: number;
|
|
138
|
+
maxZoom?: number;
|
|
139
|
+
preload?: number;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** sMap raster tiles as an OpenLayers tile layer, with the sMap badge. */
|
|
143
|
+
export declare class SMapRasterLayer extends TileLayer<SMapRasterSource> {
|
|
144
|
+
constructor(options?: SMapRasterLayerOptions);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** The sMap badge as an OpenLayers control. */
|
|
148
|
+
export declare class SMapBadge extends Control {
|
|
149
|
+
constructor(options?: { document?: Document });
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export declare function smapLayer(options?: SMapLayerOptions): SMapLayer;
|
|
153
|
+
export declare function smapRasterSource(options?: SMapRasterSourceOptions): SMapRasterSource;
|
|
154
|
+
export declare function smapRasterLayer(options?: SMapRasterLayerOptions): SMapRasterLayer;
|
|
155
|
+
/** The vector map where WebGL 2 exists, raster tiles elsewhere (`mode`, default `auto`). */
|
|
156
|
+
export declare function smapBasemap(options?: (SMapLayerOptions & SMapRasterLayerOptions) & { mode?: 'auto' | 'vector' | 'raster' }): SMapLayer | SMapRasterLayer;
|
|
157
|
+
export declare function hasWebGL2(doc?: Document): boolean;
|
|
158
|
+
export declare function checkStyle(style?: string): SMapStyle;
|
|
159
|
+
export declare function rasterPath(style: SMapStyle, z: number, x: number, y: number, options?: { lang?: string; retina?: boolean }): string;
|
|
160
|
+
export declare function stylePath(style: SMapStyle, lang?: string): string;
|
|
161
|
+
export declare const styles: StyleFlavor[];
|
|
162
|
+
export declare const version: string;
|
|
163
|
+
export declare const DEFAULT_BASE: string;
|
|
164
|
+
export declare const OSM_ATTRIBUTION: string;
|
|
165
|
+
export declare const FORWARDED: string[];
|
|
166
|
+
|
|
167
|
+
declare const SMapOpenLayers: {
|
|
168
|
+
version: string;
|
|
169
|
+
styles: StyleFlavor[];
|
|
170
|
+
SMapLayer: typeof SMapLayer;
|
|
171
|
+
smapLayer: typeof smapLayer;
|
|
172
|
+
SMapRasterSource: typeof SMapRasterSource;
|
|
173
|
+
smapRasterSource: typeof smapRasterSource;
|
|
174
|
+
SMapRasterLayer: typeof SMapRasterLayer;
|
|
175
|
+
smapRasterLayer: typeof smapRasterLayer;
|
|
176
|
+
smapBasemap: typeof smapBasemap;
|
|
177
|
+
SMapBadge: typeof SMapBadge;
|
|
178
|
+
SMapAccess: typeof SMapAccess;
|
|
179
|
+
hasWebGL2: typeof hasWebGL2;
|
|
180
|
+
rasterPath: typeof rasterPath;
|
|
181
|
+
checkStyle: typeof checkStyle;
|
|
182
|
+
};
|
|
183
|
+
export default SMapOpenLayers;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Types of @superrouteca/smap-openlayers/on-smap: OpenLayers sources and layers on an sMap map.
|
|
2
|
+
import type BaseLayer from 'ol/layer/Base.js';
|
|
3
|
+
import type Source from 'ol/source/Source.js';
|
|
4
|
+
import type OlMap from 'ol/Map.js';
|
|
5
|
+
import type LayerGroup from 'ol/layer/Group.js';
|
|
6
|
+
import type { Map as SMapMap, StyleLayer, Slot } from '@superrouteca/smap';
|
|
7
|
+
|
|
8
|
+
export interface AddOptions {
|
|
9
|
+
slot?: Slot;
|
|
10
|
+
before?: string;
|
|
11
|
+
zIndex?: number;
|
|
12
|
+
/** Style Specification layers drawing a vector tile source. */
|
|
13
|
+
layers?: StyleLayer[];
|
|
14
|
+
/** The projection of a vector source's features (default the source's, else EPSG:3857). */
|
|
15
|
+
projection?: string;
|
|
16
|
+
/** ol/format/GeoJSON, when it should not be imported on demand. */
|
|
17
|
+
GeoJSON?: new () => { writeFeaturesObject(features: unknown[], options?: unknown): { type: 'FeatureCollection'; features: any[] } };
|
|
18
|
+
/** sMap layer options for a vector source's features (popup, marker, color, …). */
|
|
19
|
+
[smapOption: string]: unknown;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type SourceKind = 'xyz' | 'wms' | 'wmts' | 'vectortile' | 'vector';
|
|
23
|
+
|
|
24
|
+
/** Adds an OpenLayers layer or source to an sMap map; resolves to the ids added. */
|
|
25
|
+
export declare function addOpenLayersLayer(smap: SMapMap, id: string, layerOrSource: BaseLayer | Source, options?: AddOptions): Promise<string[]>;
|
|
26
|
+
/** Adds every layer of an OpenLayers map, group or list, in order, as `<prefix><n>`. */
|
|
27
|
+
export declare function addOpenLayersLayers(smap: SMapMap, layers: OlMap | LayerGroup | BaseLayer[], options?: { prefix?: string; layerOptions?: Record<number, AddOptions> }): Promise<{ added: string[]; skipped: Array<{ index: number; reason: string }> }>;
|
|
28
|
+
export declare function sourceKind(source: unknown): SourceKind | null;
|
|
29
|
+
export declare function expandTemplates(urls: string[]): string[];
|
|
30
|
+
export declare function wmtsTemplate(source: unknown): string[] | null;
|
|
31
|
+
export declare function styleOptions(style: unknown): { points?: Record<string, unknown>; lines?: Record<string, unknown>; polygons?: Record<string, unknown> };
|