MapboxImageryProvider.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. import Credit from '../Core/Credit.js';
  2. import defaultValue from '../Core/defaultValue.js';
  3. import defined from '../Core/defined.js';
  4. import defineProperties from '../Core/defineProperties.js';
  5. import DeveloperError from '../Core/DeveloperError.js';
  6. import MapboxApi from '../Core/MapboxApi.js';
  7. import Resource from '../Core/Resource.js';
  8. import UrlTemplateImageryProvider from './UrlTemplateImageryProvider.js';
  9. var trailingSlashRegex = /\/$/;
  10. var defaultCredit = new Credit('&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. * Provides tiled imagery hosted by Mapbox.
  13. *
  14. * @alias MapboxImageryProvider
  15. * @constructor
  16. *
  17. * @param {Object} [options] Object with the following properties:
  18. * @param {String} [options.url='https://api.mapbox.com/v4/'] The Mapbox server url.
  19. * @param {String} options.mapId The Mapbox Map ID.
  20. * @param {String} [options.accessToken] The public access token for the imagery.
  21. * @param {String} [options.format='png'] The format of the image request.
  22. * @param {Ellipsoid} [options.ellipsoid] The ellipsoid. If not specified, the WGS84 ellipsoid is used.
  23. * @param {Number} [options.minimumLevel=0] The minimum level-of-detail supported by the imagery provider. Take care when specifying
  24. * this that the number of tiles at the minimum level is small, such as four or less. A larger number is likely
  25. * to result in rendering problems.
  26. * @param {Number} [options.maximumLevel] The maximum level-of-detail supported by the imagery provider, or undefined if there is no limit.
  27. * @param {Rectangle} [options.rectangle=Rectangle.MAX_VALUE] The rectangle, in radians, covered by the image.
  28. * @param {Credit|String} [options.credit] A credit for the data source, which is displayed on the canvas.
  29. *
  30. *
  31. * @example
  32. * // Mapbox tile provider
  33. * var mapbox = new Cesium.MapboxImageryProvider({
  34. * mapId: 'mapbox.streets',
  35. * accessToken: 'thisIsMyAccessToken'
  36. * });
  37. *
  38. * @see {@link https://www.mapbox.com/developers/api/maps/#tiles}
  39. * @see {@link https://www.mapbox.com/developers/api/#access-tokens}
  40. */
  41. function MapboxImageryProvider(options) {
  42. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  43. var mapId = options.mapId;
  44. //>>includeStart('debug', pragmas.debug);
  45. if (!defined(mapId)) {
  46. throw new DeveloperError('options.mapId is required.');
  47. }
  48. //>>includeEnd('debug');
  49. var resource = Resource.createIfNeeded(defaultValue(options.url, 'https://{s}.tiles.mapbox.com/v4/'));
  50. var accessToken = MapboxApi.getAccessToken(options.accessToken);
  51. this._mapId = mapId;
  52. this._accessToken = accessToken;
  53. this._accessTokenErrorCredit = Credit.clone(MapboxApi.getErrorCredit(options.accessToken));
  54. var format = defaultValue(options.format, 'png');
  55. if (!/\./.test(format)) {
  56. format = '.' + format;
  57. }
  58. this._format = format;
  59. var templateUrl = resource.getUrlComponent();
  60. if (!trailingSlashRegex.test(templateUrl)) {
  61. templateUrl += '/';
  62. }
  63. templateUrl += mapId + '/{z}/{x}/{y}' + this._format;
  64. resource.url = templateUrl;
  65. resource.setQueryParameters({
  66. access_token: accessToken
  67. });
  68. var credit;
  69. if (defined(options.credit)) {
  70. credit = options.credit;
  71. if (typeof credit === 'string') {
  72. credit = new Credit(credit);
  73. }
  74. } else {
  75. credit = defaultCredit;
  76. }
  77. this._resource = resource;
  78. this._imageryProvider = new UrlTemplateImageryProvider({
  79. url: resource,
  80. credit: credit,
  81. ellipsoid: options.ellipsoid,
  82. minimumLevel: options.minimumLevel,
  83. maximumLevel: options.maximumLevel,
  84. rectangle: options.rectangle
  85. });
  86. }
  87. defineProperties(MapboxImageryProvider.prototype, {
  88. /**
  89. * Gets the URL of the Mapbox server.
  90. * @memberof MapboxImageryProvider.prototype
  91. * @type {String}
  92. * @readonly
  93. */
  94. url : {
  95. get : function() {
  96. return this._imageryProvider.url;
  97. }
  98. },
  99. /**
  100. * Gets a value indicating whether or not the provider is ready for use.
  101. * @memberof MapboxImageryProvider.prototype
  102. * @type {Boolean}
  103. * @readonly
  104. */
  105. ready : {
  106. get : function() {
  107. return this._imageryProvider.ready;
  108. }
  109. },
  110. /**
  111. * Gets a promise that resolves to true when the provider is ready for use.
  112. * @memberof MapboxImageryProvider.prototype
  113. * @type {Promise.<Boolean>}
  114. * @readonly
  115. */
  116. readyPromise : {
  117. get : function() {
  118. return this._imageryProvider.readyPromise;
  119. }
  120. },
  121. /**
  122. * Gets the rectangle, in radians, of the imagery provided by the instance. This function should
  123. * not be called before {@link MapboxImageryProvider#ready} returns true.
  124. * @memberof MapboxImageryProvider.prototype
  125. * @type {Rectangle}
  126. * @readonly
  127. */
  128. rectangle: {
  129. get : function() {
  130. return this._imageryProvider.rectangle;
  131. }
  132. },
  133. /**
  134. * Gets the width of each tile, in pixels. This function should
  135. * not be called before {@link MapboxImageryProvider#ready} returns true.
  136. * @memberof MapboxImageryProvider.prototype
  137. * @type {Number}
  138. * @readonly
  139. */
  140. tileWidth : {
  141. get : function() {
  142. return this._imageryProvider.tileWidth;
  143. }
  144. },
  145. /**
  146. * Gets the height of each tile, in pixels. This function should
  147. * not be called before {@link MapboxImageryProvider#ready} returns true.
  148. * @memberof MapboxImageryProvider.prototype
  149. * @type {Number}
  150. * @readonly
  151. */
  152. tileHeight : {
  153. get : function() {
  154. return this._imageryProvider.tileHeight;
  155. }
  156. },
  157. /**
  158. * Gets the maximum level-of-detail that can be requested. This function should
  159. * not be called before {@link MapboxImageryProvider#ready} returns true.
  160. * @memberof MapboxImageryProvider.prototype
  161. * @type {Number}
  162. * @readonly
  163. */
  164. maximumLevel : {
  165. get : function() {
  166. return this._imageryProvider.maximumLevel;
  167. }
  168. },
  169. /**
  170. * Gets the minimum level-of-detail that can be requested. This function should
  171. * not be called before {@link MapboxImageryProvider#ready} returns true. Generally,
  172. * a minimum level should only be used when the rectangle of the imagery is small
  173. * enough that the number of tiles at the minimum level is small. An imagery
  174. * provider with more than a few tiles at the minimum level will lead to
  175. * rendering problems.
  176. * @memberof MapboxImageryProvider.prototype
  177. * @type {Number}
  178. * @readonly
  179. */
  180. minimumLevel : {
  181. get : function() {
  182. return this._imageryProvider.minimumLevel;
  183. }
  184. },
  185. /**
  186. * Gets the tiling scheme used by the provider. This function should
  187. * not be called before {@link MapboxImageryProvider#ready} returns true.
  188. * @memberof MapboxImageryProvider.prototype
  189. * @type {TilingScheme}
  190. * @readonly
  191. */
  192. tilingScheme : {
  193. get : function() {
  194. return this._imageryProvider.tilingScheme;
  195. }
  196. },
  197. /**
  198. * Gets the tile discard policy. If not undefined, the discard policy is responsible
  199. * for filtering out "missing" tiles via its shouldDiscardImage function. If this function
  200. * returns undefined, no tiles are filtered. This function should
  201. * not be called before {@link MapboxImageryProvider#ready} returns true.
  202. * @memberof MapboxImageryProvider.prototype
  203. * @type {TileDiscardPolicy}
  204. * @readonly
  205. */
  206. tileDiscardPolicy : {
  207. get : function() {
  208. return this._imageryProvider.tileDiscardPolicy;
  209. }
  210. },
  211. /**
  212. * Gets an event that is raised when the imagery provider encounters an asynchronous error.. By subscribing
  213. * to the event, you will be notified of the error and can potentially recover from it. Event listeners
  214. * are passed an instance of {@link TileProviderError}.
  215. * @memberof MapboxImageryProvider.prototype
  216. * @type {Event}
  217. * @readonly
  218. */
  219. errorEvent : {
  220. get : function() {
  221. return this._imageryProvider.errorEvent;
  222. }
  223. },
  224. /**
  225. * Gets the credit to display when this imagery provider is active. Typically this is used to credit
  226. * the source of the imagery. This function should
  227. * not be called before {@link MapboxImageryProvider#ready} returns true.
  228. * @memberof MapboxImageryProvider.prototype
  229. * @type {Credit}
  230. * @readonly
  231. */
  232. credit : {
  233. get : function() {
  234. return this._imageryProvider.credit;
  235. }
  236. },
  237. /**
  238. * Gets the proxy used by this provider.
  239. * @memberof MapboxImageryProvider.prototype
  240. * @type {Proxy}
  241. * @readonly
  242. */
  243. proxy : {
  244. get : function() {
  245. return this._imageryProvider.proxy;
  246. }
  247. },
  248. /**
  249. * Gets a value indicating whether or not the images provided by this imagery provider
  250. * include an alpha channel. If this property is false, an alpha channel, if present, will
  251. * be ignored. If this property is true, any images without an alpha channel will be treated
  252. * as if their alpha is 1.0 everywhere. When this property is false, memory usage
  253. * and texture upload time are reduced.
  254. * @memberof MapboxImageryProvider.prototype
  255. * @type {Boolean}
  256. * @readonly
  257. */
  258. hasAlphaChannel : {
  259. get : function() {
  260. return this._imageryProvider.hasAlphaChannel;
  261. }
  262. }
  263. });
  264. /**
  265. * Gets the credits to be displayed when a given tile is displayed.
  266. *
  267. * @param {Number} x The tile X coordinate.
  268. * @param {Number} y The tile Y coordinate.
  269. * @param {Number} level The tile level;
  270. * @returns {Credit[]} The credits to be displayed when the tile is displayed.
  271. *
  272. * @exception {DeveloperError} <code>getTileCredits</code> must not be called before the imagery provider is ready.
  273. */
  274. MapboxImageryProvider.prototype.getTileCredits = function(x, y, level) {
  275. if (defined(this._accessTokenErrorCredit)) {
  276. return [this._accessTokenErrorCredit];
  277. }
  278. };
  279. /**
  280. * Requests the image for a given tile. This function should
  281. * not be called before {@link MapboxImageryProvider#ready} returns true.
  282. *
  283. * @param {Number} x The tile X coordinate.
  284. * @param {Number} y The tile Y coordinate.
  285. * @param {Number} level The tile level.
  286. * @param {Request} [request] The request object. Intended for internal use only.
  287. * @returns {Promise.<Image|Canvas>|undefined} A promise for the image that will resolve when the image is available, or
  288. * undefined if there are too many active requests to the server, and the request
  289. * should be retried later. The resolved image may be either an
  290. * Image or a Canvas DOM object.
  291. *
  292. * @exception {DeveloperError} <code>requestImage</code> must not be called before the imagery provider is ready.
  293. */
  294. MapboxImageryProvider.prototype.requestImage = function(x, y, level, request) {
  295. return this._imageryProvider.requestImage(x, y, level, request);
  296. };
  297. /**
  298. * Asynchronously determines what features, if any, are located at a given longitude and latitude within
  299. * a tile. This function should not be called before {@link MapboxImageryProvider#ready} returns true.
  300. * This function is optional, so it may not exist on all ImageryProviders.
  301. *
  302. *
  303. * @param {Number} x The tile X coordinate.
  304. * @param {Number} y The tile Y coordinate.
  305. * @param {Number} level The tile level.
  306. * @param {Number} longitude The longitude at which to pick features.
  307. * @param {Number} latitude The latitude at which to pick features.
  308. * @return {Promise.<ImageryLayerFeatureInfo[]>|undefined} A promise for the picked features that will resolve when the asynchronous
  309. * picking completes. The resolved value is an array of {@link ImageryLayerFeatureInfo}
  310. * instances. The array may be empty if no features are found at the given location.
  311. * It may also be undefined if picking is not supported.
  312. *
  313. * @exception {DeveloperError} <code>pickFeatures</code> must not be called before the imagery provider is ready.
  314. */
  315. MapboxImageryProvider.prototype.pickFeatures = function(x, y, level, longitude, latitude) {
  316. return this._imageryProvider.pickFeatures(x, y, level, longitude, latitude);
  317. };
  318. // Exposed for tests
  319. MapboxImageryProvider._defaultCredit = defaultCredit;
  320. export default MapboxImageryProvider;