MapboxStyleImageryProvider.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. import Credit from "../Core/Credit.js";
  2. import defaultValue from "../Core/defaultValue.js";
  3. import defined from "../Core/defined.js";
  4. import DeveloperError from "../Core/DeveloperError.js";
  5. import MapboxApi from "../Core/MapboxApi.js";
  6. import Resource from "../Core/Resource.js";
  7. import UrlTemplateImageryProvider from "./UrlTemplateImageryProvider.js";
  8. var trailingSlashRegex = /\/$/;
  9. var defaultCredit = new Credit(
  10. '&copy; <a href="https://www.mapbox.com/about/maps/">Mapbox</a> &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> <strong><a href="https://www.mapbox.com/map-feedback/">Improve this map</a></strong>'
  11. );
  12. /**
  13. * @typedef {Object} MapboxStyleImageryProvider.ConstructorOptions
  14. *
  15. * Initialization options for the MapboxStyleImageryProvider constructor
  16. *
  17. * @property {Resource|String} [url='https://api.mapbox.com/styles/v1/'] The Mapbox server url.
  18. * @property {String} [username='mapbox'] The username of the map account.
  19. * @property {String} styleId The Mapbox Style ID.
  20. * @property {String} accessToken The public access token for the imagery.
  21. * @property {Number} [tilesize=512] The size of the image tiles.
  22. * @property {Boolean} [scaleFactor] Determines if tiles are rendered at a @2x scale factor.
  23. * @property {Ellipsoid} [ellipsoid] The ellipsoid. If not specified, the WGS84 ellipsoid is used.
  24. * @property {Number} [minimumLevel=0] The minimum level-of-detail supported by the imagery provider. Take care when specifying
  25. * this that the number of tiles at the minimum level is small, such as four or less. A larger number is likely
  26. * to result in rendering problems.
  27. * @property {Number} [maximumLevel] The maximum level-of-detail supported by the imagery provider, or undefined if there is no limit.
  28. * @property {Rectangle} [rectangle=Rectangle.MAX_VALUE] The rectangle, in radians, covered by the image.
  29. * @property {Credit|String} [credit] A credit for the data source, which is displayed on the canvas.
  30. */
  31. /**
  32. * Provides tiled imagery hosted by Mapbox.
  33. *
  34. * @alias MapboxStyleImageryProvider
  35. * @constructor
  36. *
  37. * @param {MapboxStyleImageryProvider.ConstructorOptions} options Object describing initialization options
  38. *
  39. * @example
  40. * // Mapbox style provider
  41. * var mapbox = new Cesium.MapboxStyleImageryProvider({
  42. * styleId: 'streets-v11',
  43. * accessToken: 'thisIsMyAccessToken'
  44. * });
  45. *
  46. * @see {@link https://docs.mapbox.com/api/maps/#styles}
  47. * @see {@link https://docs.mapbox.com/api/#access-tokens-and-token-scopes}
  48. */
  49. function MapboxStyleImageryProvider(options) {
  50. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  51. var styleId = options.styleId;
  52. //>>includeStart('debug', pragmas.debug);
  53. if (!defined(styleId)) {
  54. throw new DeveloperError("options.styleId is required.");
  55. }
  56. //>>includeEnd('debug');
  57. var accessToken = MapboxApi.getAccessToken(options.accessToken);
  58. //>>includeStart('debug', pragmas.debug);
  59. if (!defined(accessToken)) {
  60. throw new DeveloperError("options.accessToken is required.");
  61. }
  62. //>>includeEnd('debug');
  63. /**
  64. * The default alpha blending value of this provider, with 0.0 representing fully transparent and
  65. * 1.0 representing fully opaque.
  66. *
  67. * @type {Number|undefined}
  68. * @default undefined
  69. */
  70. this.defaultAlpha = undefined;
  71. /**
  72. * The default alpha blending value on the night side of the globe of this provider, with 0.0 representing fully transparent and
  73. * 1.0 representing fully opaque.
  74. *
  75. * @type {Number|undefined}
  76. * @default undefined
  77. */
  78. this.defaultNightAlpha = undefined;
  79. /**
  80. * The default alpha blending value on the day side of the globe of this provider, with 0.0 representing fully transparent and
  81. * 1.0 representing fully opaque.
  82. *
  83. * @type {Number|undefined}
  84. * @default undefined
  85. */
  86. this.defaultDayAlpha = undefined;
  87. /**
  88. * The default brightness of this provider. 1.0 uses the unmodified imagery color. Less than 1.0
  89. * makes the imagery darker while greater than 1.0 makes it brighter.
  90. *
  91. * @type {Number|undefined}
  92. * @default undefined
  93. */
  94. this.defaultBrightness = undefined;
  95. /**
  96. * The default contrast of this provider. 1.0 uses the unmodified imagery color. Less than 1.0 reduces
  97. * the contrast while greater than 1.0 increases it.
  98. *
  99. * @type {Number|undefined}
  100. * @default undefined
  101. */
  102. this.defaultContrast = undefined;
  103. /**
  104. * The default hue of this provider in radians. 0.0 uses the unmodified imagery color.
  105. *
  106. * @type {Number|undefined}
  107. * @default undefined
  108. */
  109. this.defaultHue = undefined;
  110. /**
  111. * The default saturation of this provider. 1.0 uses the unmodified imagery color. Less than 1.0 reduces the
  112. * saturation while greater than 1.0 increases it.
  113. *
  114. * @type {Number|undefined}
  115. * @default undefined
  116. */
  117. this.defaultSaturation = undefined;
  118. /**
  119. * The default gamma correction to apply to this provider. 1.0 uses the unmodified imagery color.
  120. *
  121. * @type {Number|undefined}
  122. * @default undefined
  123. */
  124. this.defaultGamma = undefined;
  125. /**
  126. * The default texture minification filter to apply to this provider.
  127. *
  128. * @type {TextureMinificationFilter}
  129. * @default undefined
  130. */
  131. this.defaultMinificationFilter = undefined;
  132. /**
  133. * The default texture magnification filter to apply to this provider.
  134. *
  135. * @type {TextureMagnificationFilter}
  136. * @default undefined
  137. */
  138. this.defaultMagnificationFilter = undefined;
  139. var resource = Resource.createIfNeeded(
  140. defaultValue(options.url, "https://api.mapbox.com/styles/v1/")
  141. );
  142. this._styleId = styleId;
  143. this._accessToken = accessToken;
  144. var tilesize = defaultValue(options.tilesize, 512);
  145. this._tilesize = tilesize;
  146. var username = defaultValue(options.username, "mapbox");
  147. this._username = username;
  148. var scaleFactor = defined(options.scaleFactor) ? "@2x" : "";
  149. var templateUrl = resource.getUrlComponent();
  150. if (!trailingSlashRegex.test(templateUrl)) {
  151. templateUrl += "/";
  152. }
  153. templateUrl +=
  154. this._username +
  155. "/" +
  156. styleId +
  157. "/tiles/" +
  158. this._tilesize +
  159. "/{z}/{x}/{y}" +
  160. scaleFactor;
  161. resource.url = templateUrl;
  162. resource.setQueryParameters({
  163. access_token: accessToken,
  164. });
  165. var credit;
  166. if (defined(options.credit)) {
  167. credit = options.credit;
  168. if (typeof credit === "string") {
  169. credit = new Credit(credit);
  170. }
  171. } else {
  172. credit = defaultCredit;
  173. }
  174. this._resource = resource;
  175. this._imageryProvider = new UrlTemplateImageryProvider({
  176. url: resource,
  177. credit: credit,
  178. ellipsoid: options.ellipsoid,
  179. minimumLevel: options.minimumLevel,
  180. maximumLevel: options.maximumLevel,
  181. rectangle: options.rectangle,
  182. });
  183. }
  184. Object.defineProperties(MapboxStyleImageryProvider.prototype, {
  185. /**
  186. * Gets the URL of the Mapbox server.
  187. * @memberof MapboxStyleImageryProvider.prototype
  188. * @type {String}
  189. * @readonly
  190. */
  191. url: {
  192. get: function () {
  193. return this._imageryProvider.url;
  194. },
  195. },
  196. /**
  197. * Gets a value indicating whether or not the provider is ready for use.
  198. * @memberof MapboxStyleImageryProvider.prototype
  199. * @type {Boolean}
  200. * @readonly
  201. */
  202. ready: {
  203. get: function () {
  204. return this._imageryProvider.ready;
  205. },
  206. },
  207. /**
  208. * Gets a promise that resolves to true when the provider is ready for use.
  209. * @memberof MapboxStyleImageryProvider.prototype
  210. * @type {Promise.<Boolean>}
  211. * @readonly
  212. */
  213. readyPromise: {
  214. get: function () {
  215. return this._imageryProvider.readyPromise;
  216. },
  217. },
  218. /**
  219. * Gets the rectangle, in radians, of the imagery provided by the instance. This function should
  220. * not be called before {@link MapboxStyleImageryProvider#ready} returns true.
  221. * @memberof MapboxStyleImageryProvider.prototype
  222. * @type {Rectangle}
  223. * @readonly
  224. */
  225. rectangle: {
  226. get: function () {
  227. return this._imageryProvider.rectangle;
  228. },
  229. },
  230. /**
  231. * Gets the width of each tile, in pixels. This function should
  232. * not be called before {@link MapboxStyleImageryProvider#ready} returns true.
  233. * @memberof MapboxStyleImageryProvider.prototype
  234. * @type {Number}
  235. * @readonly
  236. */
  237. tileWidth: {
  238. get: function () {
  239. return this._imageryProvider.tileWidth;
  240. },
  241. },
  242. /**
  243. * Gets the height of each tile, in pixels. This function should
  244. * not be called before {@link MapboxStyleImageryProvider#ready} returns true.
  245. * @memberof MapboxStyleImageryProvider.prototype
  246. * @type {Number}
  247. * @readonly
  248. */
  249. tileHeight: {
  250. get: function () {
  251. return this._imageryProvider.tileHeight;
  252. },
  253. },
  254. /**
  255. * Gets the maximum level-of-detail that can be requested. This function should
  256. * not be called before {@link MapboxStyleImageryProvider#ready} returns true.
  257. * @memberof MapboxStyleImageryProvider.prototype
  258. * @type {Number|undefined}
  259. * @readonly
  260. */
  261. maximumLevel: {
  262. get: function () {
  263. return this._imageryProvider.maximumLevel;
  264. },
  265. },
  266. /**
  267. * Gets the minimum level-of-detail that can be requested. This function should
  268. * not be called before {@link MapboxStyleImageryProvider#ready} returns true. Generally,
  269. * a minimum level should only be used when the rectangle of the imagery is small
  270. * enough that the number of tiles at the minimum level is small. An imagery
  271. * provider with more than a few tiles at the minimum level will lead to
  272. * rendering problems.
  273. * @memberof MapboxStyleImageryProvider.prototype
  274. * @type {Number}
  275. * @readonly
  276. */
  277. minimumLevel: {
  278. get: function () {
  279. return this._imageryProvider.minimumLevel;
  280. },
  281. },
  282. /**
  283. * Gets the tiling scheme used by the provider. This function should
  284. * not be called before {@link MapboxStyleImageryProvider#ready} returns true.
  285. * @memberof MapboxStyleImageryProvider.prototype
  286. * @type {TilingScheme}
  287. * @readonly
  288. */
  289. tilingScheme: {
  290. get: function () {
  291. return this._imageryProvider.tilingScheme;
  292. },
  293. },
  294. /**
  295. * Gets the tile discard policy. If not undefined, the discard policy is responsible
  296. * for filtering out "missing" tiles via its shouldDiscardImage function. If this function
  297. * returns undefined, no tiles are filtered. This function should
  298. * not be called before {@link MapboxStyleImageryProvider#ready} returns true.
  299. * @memberof MapboxStyleImageryProvider.prototype
  300. * @type {TileDiscardPolicy}
  301. * @readonly
  302. */
  303. tileDiscardPolicy: {
  304. get: function () {
  305. return this._imageryProvider.tileDiscardPolicy;
  306. },
  307. },
  308. /**
  309. * Gets an event that is raised when the imagery provider encounters an asynchronous error.. By subscribing
  310. * to the event, you will be notified of the error and can potentially recover from it. Event listeners
  311. * are passed an instance of {@link TileProviderError}.
  312. * @memberof MapboxStyleImageryProvider.prototype
  313. * @type {Event}
  314. * @readonly
  315. */
  316. errorEvent: {
  317. get: function () {
  318. return this._imageryProvider.errorEvent;
  319. },
  320. },
  321. /**
  322. * Gets the credit to display when this imagery provider is active. Typically this is used to credit
  323. * the source of the imagery. This function should
  324. * not be called before {@link MapboxStyleImageryProvider#ready} returns true.
  325. * @memberof MapboxStyleImageryProvider.prototype
  326. * @type {Credit}
  327. * @readonly
  328. */
  329. credit: {
  330. get: function () {
  331. return this._imageryProvider.credit;
  332. },
  333. },
  334. /**
  335. * Gets the proxy used by this provider.
  336. * @memberof MapboxStyleImageryProvider.prototype
  337. * @type {Proxy}
  338. * @readonly
  339. */
  340. proxy: {
  341. get: function () {
  342. return this._imageryProvider.proxy;
  343. },
  344. },
  345. /**
  346. * Gets a value indicating whether or not the images provided by this imagery provider
  347. * include an alpha channel. If this property is false, an alpha channel, if present, will
  348. * be ignored. If this property is true, any images without an alpha channel will be treated
  349. * as if their alpha is 1.0 everywhere. When this property is false, memory usage
  350. * and texture upload time are reduced.
  351. * @memberof MapboxStyleImageryProvider.prototype
  352. * @type {Boolean}
  353. * @readonly
  354. */
  355. hasAlphaChannel: {
  356. get: function () {
  357. return this._imageryProvider.hasAlphaChannel;
  358. },
  359. },
  360. });
  361. /**
  362. * Gets the credits to be displayed when a given tile is displayed.
  363. *
  364. * @param {Number} x The tile X coordinate.
  365. * @param {Number} y The tile Y coordinate.
  366. * @param {Number} level The tile level;
  367. * @returns {Credit[]} The credits to be displayed when the tile is displayed.
  368. *
  369. * @exception {DeveloperError} <code>getTileCredits</code> must not be called before the imagery provider is ready.
  370. */
  371. MapboxStyleImageryProvider.prototype.getTileCredits = function (x, y, level) {
  372. return undefined;
  373. };
  374. /**
  375. * Requests the image for a given tile. This function should
  376. * not be called before {@link MapboxStyleImageryProvider#ready} returns true.
  377. *
  378. * @param {Number} x The tile X coordinate.
  379. * @param {Number} y The tile Y coordinate.
  380. * @param {Number} level The tile level.
  381. * @param {Request} [request] The request object. Intended for internal use only.
  382. * @returns {Promise.<HTMLImageElement|HTMLCanvasElement>|undefined} A promise for the image that will resolve when the image is available, or
  383. * undefined if there are too many active requests to the server, and the request
  384. * should be retried later. The resolved image may be either an
  385. * Image or a Canvas DOM object.
  386. *
  387. * @exception {DeveloperError} <code>requestImage</code> must not be called before the imagery provider is ready.
  388. */
  389. MapboxStyleImageryProvider.prototype.requestImage = function (
  390. x,
  391. y,
  392. level,
  393. request
  394. ) {
  395. return this._imageryProvider.requestImage(x, y, level, request);
  396. };
  397. /**
  398. * Asynchronously determines what features, if any, are located at a given longitude and latitude within
  399. * a tile. This function should not be called before {@link MapboxStyleImageryProvider#ready} returns true.
  400. * This function is optional, so it may not exist on all ImageryProviders.
  401. *
  402. *
  403. * @param {Number} x The tile X coordinate.
  404. * @param {Number} y The tile Y coordinate.
  405. * @param {Number} level The tile level.
  406. * @param {Number} longitude The longitude at which to pick features.
  407. * @param {Number} latitude The latitude at which to pick features.
  408. * @return {Promise.<ImageryLayerFeatureInfo[]>|undefined} A promise for the picked features that will resolve when the asynchronous
  409. * picking completes. The resolved value is an array of {@link ImageryLayerFeatureInfo}
  410. * instances. The array may be empty if no features are found at the given location.
  411. * It may also be undefined if picking is not supported.
  412. *
  413. * @exception {DeveloperError} <code>pickFeatures</code> must not be called before the imagery provider is ready.
  414. */
  415. MapboxStyleImageryProvider.prototype.pickFeatures = function (
  416. x,
  417. y,
  418. level,
  419. longitude,
  420. latitude
  421. ) {
  422. return this._imageryProvider.pickFeatures(x, y, level, longitude, latitude);
  423. };
  424. // Exposed for tests
  425. MapboxStyleImageryProvider._defaultCredit = defaultCredit;
  426. export default MapboxStyleImageryProvider;