ol 9.0.0-dev.1708359055761 → 9.0.0-dev.1708373609339

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.
@@ -0,0 +1,251 @@
1
+ /**
2
+ * @module ol/source/Google
3
+ */
4
+
5
+ import TileImage from './TileImage.js';
6
+ import {createXYZ, extentFromProjection} from '../tilegrid.js';
7
+
8
+ const defaultAttribution =
9
+ 'Google Maps' +
10
+ '<a class="ol-attribution-google-tos" href="https://cloud.google.com/maps-platform/terms/" target="_blank">Terms of Use</a>' +
11
+ ' and ' +
12
+ '<a class="ol-attribution-google-tos" href="https://policies.google.com/privacy" target="_blank">Privacy Policy</a>';
13
+
14
+ const createSessionUrl = 'https://tile.googleapis.com/v1/createSession';
15
+ const tileUrl = 'https://tile.googleapis.com/v1/2dtiles';
16
+ const maxZoom = 22;
17
+
18
+ /**
19
+ * @typedef {Object} Options
20
+ * @property {string} key Google Map Tiles API key. Get yours at https://developers.google.com/maps/documentation/tile/get-api-key.
21
+ * @property {string} [mapType='roadmap'] The type of [base map](https://developers.google.com/maps/documentation/tile/session_tokens#required_fields).
22
+ * @property {string} [language='en-US'] An [IETF language tag](https://en.wikipedia.org/wiki/IETF_language_tag) for information displayed on the tiles.
23
+ * @property {string} [region='US'] A [Common Locale Data Repository](https://cldr.unicode.org/) (CLDR) region identifier that represents the user location.
24
+ * @property {string} [imageFormat] The image format used for the map tiles (e.g. `'jpeg'`, or `'png'`).
25
+ * @property {string} [scale] Scale for map elements (`'scaleFactor1x'`, `'scaleFactor2x'`, or `'scaleFactor4x'`).
26
+ * @property {boolean} [highDpi=false] Use high-resolution tiles.
27
+ * @property {Array<string>} [layerTypes] The layer types added to the map (e.g. `'layerRoadmap'`, `'layerStreetview'`, or `'layerTraffic'`).
28
+ * @property {boolean} [overlay=false] Display only the `layerTypes` and not the underlying `mapType` (only works if `layerTypes` is provided).
29
+ * @property {Array<Object>} [styles] [Custom styles](https://developers.google.com/maps/documentation/tile/style-reference) applied to the map.
30
+ * @property {import("./Source.js").AttributionLike} [attributions] Attributions.
31
+ * @property {boolean} [interpolate=true] Use interpolated values when resampling. By default,
32
+ * linear interpolation is used when resampling. Set to false to use the nearest neighbor instead.
33
+ * @property {number} [cacheSize] Initial tile cache size. Will auto-grow to hold at least the number of tiles in the viewport.
34
+ * @property {number} [reprojectionErrorThreshold=0.5] Maximum allowed reprojection error (in pixels).
35
+ * Higher values can increase reprojection performance, but decrease precision.
36
+ * @property {import("../Tile.js").LoadFunction} [tileLoadFunction] Optional function to load a tile given a URL. The default is
37
+ * ```js
38
+ * function(imageTile, src) {
39
+ * imageTile.getImage().src = src;
40
+ * };
41
+ * ```
42
+ * @property {boolean} [wrapX=true] Wrap the world horizontally.
43
+ * @property {number} [transition] Duration of the opacity transition for rendering.
44
+ * To disable the opacity transition, pass `transition: 0`.
45
+ * @property {number|import("../array.js").NearestDirectionFunction} [zDirection=0]
46
+ * Choose whether to use tiles with a higher or lower zoom level when between integer
47
+ * zoom levels. See {@link module:ol/tilegrid/TileGrid~TileGrid#getZForResolution}.
48
+ */
49
+
50
+ /**
51
+ * @typedef {Object} SessionTokenRequest
52
+ * @property {string} mapType The map type.
53
+ * @property {string} language The language.
54
+ * @property {string} region The region.
55
+ * @property {string} [imageFormat] The image format.
56
+ * @property {string} [scale] The scale.
57
+ * @property {boolean} [highDpi] Use high resolution tiles.
58
+ * @property {Array<string>} [layerTypes] The layer types.
59
+ * @property {boolean} [overlay] The overlay.
60
+ * @property {Array<Object>} [styles] The styles.
61
+ */
62
+
63
+ /**
64
+ * @typedef {Object} SessionTokenResponse
65
+ * @property {string} session The session token.
66
+ * @property {string} expiry The session token expiry (seconds since the epoch as a string).
67
+ * @property {number} tileWidth The tile width.
68
+ * @property {number} tileHeight The tile height.
69
+ * @property {string} imageFormat The image format.
70
+ */
71
+
72
+ /**
73
+ * @classdesc
74
+ * A tile layer source that renders tiles from the Google [Map Tiles API](https://developers.google.com/maps/documentation/tile/overview).
75
+ * The constructor takes options that are passed to the request to create a session token. Refer to the
76
+ * [documentation](https://developers.google.com/maps/documentation/tile/session_tokens#required_fields)
77
+ * for additional details.
78
+ * @api
79
+ */
80
+ class Google extends TileImage {
81
+ /**
82
+ * @param {Options} options Google Maps options.
83
+ */
84
+ constructor(options) {
85
+ const highDpi = !!options.highDpi;
86
+ const opaque = !(options.overlay === true);
87
+ const attributions = options.attributions || [defaultAttribution];
88
+
89
+ super({
90
+ attributions: attributions,
91
+ cacheSize: options.cacheSize,
92
+ crossOrigin: 'anonymous',
93
+ interpolate: options.interpolate,
94
+ opaque: opaque,
95
+ projection: 'EPSG:3857',
96
+ reprojectionErrorThreshold: options.reprojectionErrorThreshold,
97
+ state: 'loading',
98
+ tileLoadFunction: options.tileLoadFunction,
99
+ tilePixelRatio: highDpi ? 2 : 1,
100
+ wrapX: options.wrapX !== undefined ? options.wrapX : true,
101
+ transition: options.transition,
102
+ zDirection: options.zDirection,
103
+ });
104
+
105
+ /**
106
+ * @type {string}
107
+ * @private
108
+ */
109
+ this.apiKey_ = options.key;
110
+
111
+ /**
112
+ * @type {Error|null}
113
+ */
114
+ this.error_ = null;
115
+
116
+ /**
117
+ * @type {SessionTokenRequest}
118
+ */
119
+ const sessionTokenRequest = {
120
+ mapType: options.mapType || 'roadmap',
121
+ language: options.language || 'en-US',
122
+ region: options.region || 'US',
123
+ };
124
+ if (options.imageFormat) {
125
+ sessionTokenRequest.imageFormat = options.imageFormat;
126
+ }
127
+ if (options.scale) {
128
+ sessionTokenRequest.scale = options.scale;
129
+ }
130
+ if (highDpi) {
131
+ sessionTokenRequest.highDpi = true;
132
+ }
133
+ if (options.layerTypes) {
134
+ sessionTokenRequest.layerTypes = options.layerTypes;
135
+ }
136
+ if (options.styles) {
137
+ sessionTokenRequest.styles = options.styles;
138
+ }
139
+ if (options.overlay === true) {
140
+ sessionTokenRequest.overlay = true;
141
+ }
142
+
143
+ /**
144
+ * @type {SessionTokenRequest}
145
+ * @private
146
+ */
147
+ this.sessionTokenRequest_ = sessionTokenRequest;
148
+
149
+ /**
150
+ * @type {ReturnType<typeof setTimeout>}
151
+ * @private
152
+ */
153
+ this.sessionRefreshId_;
154
+
155
+ this.createSession_();
156
+ }
157
+
158
+ /**
159
+ * @return {Error|null} A source loading error. When the source state is `error`, use this function
160
+ * to get more information about the error. To debug a faulty configuration, you may want to use
161
+ * a listener like
162
+ * ```js
163
+ * source.on('change', () => {
164
+ * if (source.getState() === 'error') {
165
+ * console.error(source.getError());
166
+ * }
167
+ * });
168
+ * ```
169
+ */
170
+ getError() {
171
+ return this.error_;
172
+ }
173
+
174
+ /**
175
+ * Exposed here so it can be overridden in the tests.
176
+ * @param {string} url The URL.
177
+ * @param {RequestInit} config The config.
178
+ * @return {Promise<Response>} A promise that resolves with the response.
179
+ */
180
+ fetchSessionToken(url, config) {
181
+ return fetch(url, config);
182
+ }
183
+
184
+ /**
185
+ * Get or renew a session token for use with tile requests.
186
+ * @private
187
+ */
188
+ async createSession_() {
189
+ const url = createSessionUrl + '?key=' + this.apiKey_;
190
+ const config = {
191
+ method: 'POST',
192
+ headers: {
193
+ 'Content-Type': 'application/json',
194
+ },
195
+ body: JSON.stringify(this.sessionTokenRequest_),
196
+ };
197
+
198
+ const response = await this.fetchSessionToken(url, config);
199
+ if (!response.ok) {
200
+ try {
201
+ const body = await response.json();
202
+ this.error_ = new Error(body.error.message);
203
+ } catch {
204
+ this.error_ = new Error('Error fetching session token');
205
+ }
206
+ this.setState('error');
207
+ return;
208
+ }
209
+
210
+ /**
211
+ * @type {SessionTokenResponse}
212
+ */
213
+ const sessionTokenResponse = await response.json();
214
+
215
+ const tilePixelRatio = this.getTilePixelRatio(1);
216
+ const tileSize = [
217
+ sessionTokenResponse.tileWidth / tilePixelRatio,
218
+ sessionTokenResponse.tileHeight / tilePixelRatio,
219
+ ];
220
+
221
+ this.tileGrid = createXYZ({
222
+ extent: extentFromProjection(this.getProjection()),
223
+ maxZoom: maxZoom,
224
+ tileSize: tileSize,
225
+ });
226
+
227
+ const session = sessionTokenResponse.session;
228
+ const key = this.apiKey_;
229
+ this.tileUrlFunction = function (tileCoord, pixelRatio, projection) {
230
+ const z = tileCoord[0];
231
+ const x = tileCoord[1];
232
+ const y = tileCoord[2];
233
+ const url = `${tileUrl}/${z}/${x}/${y}?session=${session}&key=${key}`;
234
+ return url;
235
+ };
236
+
237
+ const expiry = parseInt(sessionTokenResponse.expiry, 10) * 1000;
238
+ const timeout = Math.max(expiry - Date.now() - 60 * 1000, 1);
239
+ this.sessionRefreshId_ = setTimeout(() => this.createSession_(), timeout);
240
+
241
+ // even if the state is already ready, we want the change event
242
+ this.setState('ready');
243
+ }
244
+
245
+ disposeInternal() {
246
+ clearTimeout(this.sessionRefreshId_);
247
+ super.disposeInternal();
248
+ }
249
+ }
250
+
251
+ export default Google;
package/util.js CHANGED
@@ -33,4 +33,4 @@ export function getUid(obj) {
33
33
  * OpenLayers version.
34
34
  * @type {string}
35
35
  */
36
- export const VERSION = '9.0.0-dev.1708359055761';
36
+ export const VERSION = '9.0.0-dev.1708373609339';