Merge pull request #13552 from ahocevar/ol-mapbox-style-8

Updates for ol-mapbox-style v8
This commit is contained in:
Andreas Hocevar
2022-04-11 21:20:45 +02:00
committed by GitHub
7 changed files with 179 additions and 527 deletions

View File

@@ -5,9 +5,9 @@ import TileQueue, {
import VectorTileLayer from '../src/ol/layer/VectorTile.js';
import VectorTileSource from '../src/ol/source/VectorTile.js';
import stringify from 'json-stringify-safe';
import styleFunction from 'ol-mapbox-style/dist/stylefunction.js';
import {get} from '../src/ol/proj.js';
import {inView} from '../src/ol/layer/Layer.js';
import {stylefunction} from 'ol-mapbox-style';
/** @type {any} */
const worker = self;
@@ -95,7 +95,7 @@ function loadStyles() {
};
rendererTransform = transform;
};
styleFunction(
stylefunction(
layer,
styleJson,
bucket.layers,

View File

@@ -1,55 +1,36 @@
import MVT from '../src/ol/format/MVT.js';
import TileGrid from '../src/ol/tilegrid/TileGrid.js';
import VectorTileLayer from '../src/ol/layer/VectorTile.js';
import VectorTileSource from '../src/ol/source/VectorTile.js';
import View from '../src/ol/View.js';
import olms from 'ol-mapbox-style';
import {defaultResolutions} from 'ol-mapbox-style/dist/util.js';
import {Map, View} from '../src/ol/index.js';
import {applyBackground, applyStyle} from 'ol-mapbox-style';
import {createXYZ} from '../src/ol/tilegrid.js';
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
const url = 'https://api.maptiler.com/maps/basic-4326/style.json?key=' + key;
// Match the server resolutions
const maxResolution = 360 / 512;
defaultResolutions.length = 14;
for (let i = 0; i < 14; ++i) {
defaultResolutions[i] = maxResolution / Math.pow(2, i + 1);
}
olms(
'map',
'https://api.maptiler.com/maps/basic-4326/style.json?key=' + key
).then(function (map) {
// Custom tile grid for the EPSG:4326 projection
const tileGrid = new TileGrid({
extent: [-180, -90, 180, 90],
tileSize: 512,
resolutions: defaultResolutions,
});
const mapboxStyle = map.get('mapbox-style');
// Replace the source with a EPSG:4326 projection source for each vector tile layer
map.getLayers().forEach(function (layer) {
const mapboxSource = layer.get('mapbox-source');
if (mapboxSource && mapboxStyle.sources[mapboxSource].type === 'vector') {
const source = layer.getSource();
layer.setSource(
new VectorTileSource({
format: new MVT(),
projection: 'EPSG:4326',
urls: source.getUrls(),
tileGrid: tileGrid,
})
);
}
});
// Configure the map with a view with EPSG:4326 projection
map.setView(
new View({
projection: 'EPSG:4326',
zoom: mapboxStyle.zoom,
center: mapboxStyle.center,
})
);
const tileGrid = createXYZ({
extent: [-180, -90, 180, 90],
tileSize: 512,
maxResolution: 180 / 512,
maxZoom: 13,
});
const layer = new VectorTileLayer({
declutter: true,
source: new VectorTileSource({
projection: 'EPSG:4326',
tileGrid: tileGrid,
}),
});
applyStyle(layer, url, '', {resolutions: tileGrid.getResolutions()});
applyBackground(layer, url);
const map = new Map({
target: 'map',
layers: [layer],
view: new View({
projection: 'EPSG:4326',
zoom: 0,
center: [0, 30],
}),
});

121
package-lock.json generated
View File

@@ -10,7 +10,7 @@
"license": "BSD-2-Clause",
"dependencies": {
"geotiff": "^2.0.2",
"ol-mapbox-style": "^7.1.1",
"ol-mapbox-style": "^8.0.5",
"pbf": "3.2.1",
"rbush": "^3.0.1"
},
@@ -62,6 +62,7 @@
"serve-static": "^1.14.0",
"shx": "^0.3.2",
"sinon": "^13.0.0",
"source-map-loader": "^3.0.1",
"threads": "^1.6.5",
"typescript": "4.6.3",
"walk": "^2.3.9",
@@ -1785,9 +1786,9 @@
}
},
"node_modules/@mapbox/mapbox-gl-style-spec": {
"version": "13.20.1",
"resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-style-spec/-/mapbox-gl-style-spec-13.20.1.tgz",
"integrity": "sha512-xVCJ3IbKoPwcPrxxtGAxUqHEVxXi1hnJtLIFqgkuZfnzj0KeRbk3dZlDr/KNo1/doJjIoFgPFUO/HMOT+wXGPA==",
"version": "13.24.0",
"resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-style-spec/-/mapbox-gl-style-spec-13.24.0.tgz",
"integrity": "sha512-9yhRSqnKX+59MrG647x2pACfR2Ewk8Ii5X75Ag8oToEKZU+PSY0+r10EirIVCTDwuHPzp/VuuN3j6n+Hv/gGpQ==",
"dependencies": {
"@mapbox/jsonlint-lines-primitives": "~2.0.2",
"@mapbox/point-geometry": "^0.1.0",
@@ -1799,10 +1800,10 @@
"sort-object": "^0.3.2"
},
"bin": {
"gl-style-composite": "bin/gl-style-composite",
"gl-style-format": "bin/gl-style-format",
"gl-style-migrate": "bin/gl-style-migrate",
"gl-style-validate": "bin/gl-style-validate"
"gl-style-composite": "bin/gl-style-composite.js",
"gl-style-format": "bin/gl-style-format.js",
"gl-style-migrate": "bin/gl-style-migrate.js",
"gl-style-validate": "bin/gl-style-validate.js"
}
},
"node_modules/@mapbox/point-geometry": {
@@ -2475,6 +2476,12 @@
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
"dev": true
},
"node_modules/abab": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
"integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==",
"dev": true
},
"node_modules/accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
@@ -7451,11 +7458,11 @@
"dev": true
},
"node_modules/ol-mapbox-style": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/ol-mapbox-style/-/ol-mapbox-style-7.1.1.tgz",
"integrity": "sha512-GLTEYiH/Ec9Zn1eS4S/zXyR2sierVrUc+OLVP8Ra0FRyqRhoYbXdko0b7OIeSHWdtJfHssWYefDOGxfTRUUZ/A==",
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/ol-mapbox-style/-/ol-mapbox-style-8.0.5.tgz",
"integrity": "sha512-krDZv3pBVuU52Hmk6b2oXS6z8TVTAteR6S5JmZNyNTVG+ghl8tVeNILr57BRn0ACiC0T5hF6ZPcK/Cn94XaMqg==",
"dependencies": {
"@mapbox/mapbox-gl-style-spec": "^13.20.1",
"@mapbox/mapbox-gl-style-spec": "^13.23.1",
"mapbox-to-css-font": "^2.4.1",
"webfont-matcher": "^1.1.0"
}
@@ -9066,6 +9073,48 @@
"node": ">=0.10.0"
}
},
"node_modules/source-map-js": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/source-map-loader": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.1.tgz",
"integrity": "sha512-Vp1UsfyPvgujKQzi4pyDiTOnE3E4H+yHvkVRN3c/9PJmQS4CQJExvcDvaX/D+RV+xQben9HJ56jMJS3CgUeWyA==",
"dev": true,
"dependencies": {
"abab": "^2.0.5",
"iconv-lite": "^0.6.3",
"source-map-js": "^1.0.1"
},
"engines": {
"node": ">= 12.13.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"peerDependencies": {
"webpack": "^5.0.0"
}
},
"node_modules/source-map-loader/node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dev": true,
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/source-map-support": {
"version": "0.5.19",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
@@ -11802,9 +11851,9 @@
"integrity": "sha1-zlblOfg1UrWNENZy6k1vya3HsjQ="
},
"@mapbox/mapbox-gl-style-spec": {
"version": "13.20.1",
"resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-style-spec/-/mapbox-gl-style-spec-13.20.1.tgz",
"integrity": "sha512-xVCJ3IbKoPwcPrxxtGAxUqHEVxXi1hnJtLIFqgkuZfnzj0KeRbk3dZlDr/KNo1/doJjIoFgPFUO/HMOT+wXGPA==",
"version": "13.24.0",
"resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-style-spec/-/mapbox-gl-style-spec-13.24.0.tgz",
"integrity": "sha512-9yhRSqnKX+59MrG647x2pACfR2Ewk8Ii5X75Ag8oToEKZU+PSY0+r10EirIVCTDwuHPzp/VuuN3j6n+Hv/gGpQ==",
"requires": {
"@mapbox/jsonlint-lines-primitives": "~2.0.2",
"@mapbox/point-geometry": "^0.1.0",
@@ -12429,6 +12478,12 @@
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
"dev": true
},
"abab": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
"integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==",
"dev": true
},
"accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
@@ -16194,11 +16249,11 @@
"dev": true
},
"ol-mapbox-style": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/ol-mapbox-style/-/ol-mapbox-style-7.1.1.tgz",
"integrity": "sha512-GLTEYiH/Ec9Zn1eS4S/zXyR2sierVrUc+OLVP8Ra0FRyqRhoYbXdko0b7OIeSHWdtJfHssWYefDOGxfTRUUZ/A==",
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/ol-mapbox-style/-/ol-mapbox-style-8.0.5.tgz",
"integrity": "sha512-krDZv3pBVuU52Hmk6b2oXS6z8TVTAteR6S5JmZNyNTVG+ghl8tVeNILr57BRn0ACiC0T5hF6ZPcK/Cn94XaMqg==",
"requires": {
"@mapbox/mapbox-gl-style-spec": "^13.20.1",
"@mapbox/mapbox-gl-style-spec": "^13.23.1",
"mapbox-to-css-font": "^2.4.1",
"webfont-matcher": "^1.1.0"
}
@@ -17429,6 +17484,34 @@
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
"dev": true
},
"source-map-js": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
"dev": true
},
"source-map-loader": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.1.tgz",
"integrity": "sha512-Vp1UsfyPvgujKQzi4pyDiTOnE3E4H+yHvkVRN3c/9PJmQS4CQJExvcDvaX/D+RV+xQben9HJ56jMJS3CgUeWyA==",
"dev": true,
"requires": {
"abab": "^2.0.5",
"iconv-lite": "^0.6.3",
"source-map-js": "^1.0.1"
},
"dependencies": {
"iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dev": true,
"requires": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
}
}
}
},
"source-map-support": {
"version": "0.5.19",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",

View File

@@ -46,7 +46,7 @@
},
"dependencies": {
"geotiff": "^2.0.2",
"ol-mapbox-style": "^7.1.1",
"ol-mapbox-style": "^8.0.5",
"pbf": "3.2.1",
"rbush": "^3.0.1"
},
@@ -98,6 +98,7 @@
"serve-static": "^1.14.0",
"shx": "^0.3.2",
"sinon": "^13.0.0",
"source-map-loader": "^3.0.1",
"threads": "^1.6.5",
"typescript": "4.6.3",
"walk": "^2.3.9",

View File

@@ -7,110 +7,7 @@ import MVT from '../format/MVT.js';
import SourceState from '../source/State.js';
import VectorTileLayer from '../layer/VectorTile.js';
import VectorTileSource from '../source/VectorTile.js';
import {applyBackground, applyStyle, setupVectorSource} from 'ol-mapbox-style';
const mapboxBaseUrl = 'https://api.mapbox.com';
/**
* Gets the path from a mapbox:// URL.
* @param {string} url The Mapbox URL.
* @return {string} The path.
* @private
*/
export function getMapboxPath(url) {
const startsWith = 'mapbox://';
if (url.indexOf(startsWith) !== 0) {
return '';
}
return url.slice(startsWith.length);
}
/**
* Turns mapbox:// sprite URLs into resolvable URLs.
* @param {string} url The sprite URL.
* @param {string} token The access token.
* @param {string} styleUrl The style URL.
* @return {string} A resolvable URL.
* @private
*/
export function normalizeSpriteUrl(url, token, styleUrl) {
const mapboxPath = getMapboxPath(url);
if (!mapboxPath) {
return decodeURI(new URL(url, styleUrl).href);
}
const startsWith = 'sprites/';
if (mapboxPath.indexOf(startsWith) !== 0) {
throw new Error(`unexpected sprites url: ${url}`);
}
const sprite = mapboxPath.slice(startsWith.length);
return `${mapboxBaseUrl}/styles/v1/${sprite}/sprite?access_token=${token}`;
}
/**
* Turns mapbox:// glyphs URLs into resolvable URLs.
* @param {string} url The glyphs URL.
* @param {string} token The access token.
* @param {string} styleUrl The style URL.
* @return {string} A resolvable URL.
* @private
*/
export function normalizeGlyphsUrl(url, token, styleUrl) {
const mapboxPath = getMapboxPath(url);
if (!mapboxPath) {
return decodeURI(new URL(url, styleUrl).href);
}
const startsWith = 'fonts/';
if (mapboxPath.indexOf(startsWith) !== 0) {
throw new Error(`unexpected fonts url: ${url}`);
}
const font = mapboxPath.slice(startsWith.length);
return `${mapboxBaseUrl}/fonts/v1/${font}/0-255.pbf?access_token=${token}`;
}
/**
* Turns mapbox:// style URLs into resolvable URLs.
* @param {string} url The style URL.
* @param {string} token The access token.
* @return {string} A resolvable URL.
* @private
*/
export function normalizeStyleUrl(url, token) {
const mapboxPath = getMapboxPath(url);
if (!mapboxPath) {
return decodeURI(new URL(url, location.href).href);
}
const startsWith = 'styles/';
if (mapboxPath.indexOf(startsWith) !== 0) {
throw new Error(`unexpected style url: ${url}`);
}
const style = mapboxPath.slice(startsWith.length);
return `${mapboxBaseUrl}/styles/v1/${style}?&access_token=${token}`;
}
/**
* Turns mapbox:// source URLs into vector tile URL templates.
* @param {string} url The source URL.
* @param {string} token The access token.
* @param {string} tokenParam The access token key.
* @param {string} styleUrl The style URL.
* @return {string} A vector tile template.
* @private
*/
export function normalizeSourceUrl(url, token, tokenParam, styleUrl) {
const urlObject = new URL(url, styleUrl);
const mapboxPath = getMapboxPath(url);
if (!mapboxPath) {
if (!token) {
return decodeURI(urlObject.href);
}
urlObject.searchParams.set(tokenParam, token);
return decodeURI(urlObject.href);
}
return `https://{a-d}.tiles.mapbox.com/v4/${mapboxPath}/{z}/{x}/{y}.vector.pbf?access_token=${token}`;
}
import {applyBackground, applyStyle} from 'ol-mapbox-style';
/**
* @classdesc
@@ -130,38 +27,6 @@ class ErrorEvent extends BaseEvent {
}
}
/**
* @typedef {Object} StyleObject
* @property {Object<string, SourceObject>} sources The style sources.
* @property {string} sprite The sprite URL.
* @property {string} glyphs The glyphs URL.
* @property {Array<LayerObject>} layers The style layers.
*/
/**
* @typedef {Object} SourceObject
* @property {string} url The source URL.
* @property {SourceType} type The source type.
* @property {Array<string>} [tiles] TileJSON tiles.
*/
/**
* The Mapbox source type.
* @enum {string}
*/
const SourceType = {
VECTOR: 'vector',
};
/**
* @typedef {Object} LayerObject
* @property {string} id The layer id.
* @property {string} type The layer type.
* @property {string} source The source id.
* @property {Object} layout The layout.
* @property {Object} paint The paint.
*/
/**
* @typedef {Object} Options
* @property {string} styleUrl The URL of the Mapbox style object to use for this layer. For a
@@ -306,211 +171,26 @@ class MapboxVectorLayer extends VectorTileLayer {
properties: options.properties,
});
this.setMaxResolutionFromTileGrid_ =
options.maxResolution === undefined && options.minZoom === undefined;
this.sourceId = options.source;
this.layers = options.layers;
if (options.accessToken) {
this.accessToken = options.accessToken;
} else {
const url = new URL(options.styleUrl, location.href);
// The last search parameter is the access token
url.searchParams.forEach((value, key) => {
this.accessToken = value;
this.accessTokenParam_ = key;
});
}
this.fetchStyle(options.styleUrl);
}
/**
* Fetch the style object.
* @param {string} styleUrl The URL of the style to load.
* @protected
*/
fetchStyle(styleUrl) {
const url = normalizeStyleUrl(styleUrl, this.accessToken);
fetch(url)
.then((response) => {
if (!response.ok) {
throw new Error(
`unexpected response when fetching style: ${response.status}`
);
}
return response.json();
})
.then((style) => {
this.onStyleLoad(style, url.startsWith('data:') ? location.href : url);
const url = options.styleUrl;
applyStyle(this, url, options.layers || options.source, {
accessToken: this.accessToken,
})
.then(() => {
source.setState(SourceState.READY);
})
.catch((error) => {
this.handleError(error);
this.dispatchEvent(new ErrorEvent(error));
const source = this.getSource();
source.setState(SourceState.ERROR);
});
}
/**
* Handle the loaded style object.
* @param {StyleObject} style The loaded style.
* @param {string} styleUrl The URL of the style.
* @protected
*/
onStyleLoad(style, styleUrl) {
let sourceId;
let sourceIdOrLayersList;
if (this.layers) {
// confirm all layers share the same source
const lookup = {};
for (let i = 0; i < style.layers.length; ++i) {
const layer = style.layers[i];
if (layer.source) {
lookup[layer.id] = layer.source;
}
}
let firstSource;
for (let i = 0; i < this.layers.length; ++i) {
const candidate = lookup[this.layers[i]];
if (!candidate) {
this.handleError(
new Error(`could not find source for ${this.layers[i]}`)
);
return;
}
if (!firstSource) {
firstSource = candidate;
} else if (firstSource !== candidate) {
this.handleError(
new Error(
`layers can only use a single source, found ${firstSource} and ${candidate}`
)
);
return;
}
}
sourceId = firstSource;
sourceIdOrLayersList = this.layers;
} else {
sourceId = this.sourceId;
sourceIdOrLayersList = sourceId;
}
if (!sourceIdOrLayersList) {
// default to the first source in the style
sourceId = Object.keys(style.sources)[0];
sourceIdOrLayersList = sourceId;
}
if (style.sprite) {
style.sprite = normalizeSpriteUrl(
style.sprite,
this.accessToken,
styleUrl
);
}
if (style.glyphs) {
style.glyphs = normalizeGlyphsUrl(
style.glyphs,
this.accessToken,
styleUrl
);
}
const styleSource = style.sources[sourceId];
if (styleSource.type !== SourceType.VECTOR) {
this.handleError(
new Error(`only works for vector sources, found ${styleSource.type}`)
);
return;
}
const source = this.getSource();
if (styleSource.url && styleSource.url.indexOf('mapbox://') === 0) {
// Tile source url, handle it directly
source.setUrl(
normalizeSourceUrl(
styleSource.url,
this.accessToken,
this.accessTokenParam_,
styleUrl
)
);
applyStyle(this, style, sourceIdOrLayersList)
.then(() => {
this.configureSource(source, style);
})
.catch((error) => {
this.handleError(error);
});
} else {
// TileJSON url, let ol-mapbox-style handle it
if (styleSource.tiles) {
styleSource.tiles = styleSource.tiles.map((url) =>
normalizeSourceUrl(
url,
this.accessToken,
this.accessTokenParam_,
styleUrl
)
);
}
setupVectorSource(
styleSource,
styleSource.url
? normalizeSourceUrl(
styleSource.url,
this.accessToken,
this.accessTokenParam_,
styleUrl
)
: undefined
).then((source) => {
applyStyle(this, style, sourceIdOrLayersList)
.then(() => {
this.configureSource(source, style);
})
.catch((error) => {
this.configureSource(source, style);
this.handleError(error);
});
});
}
}
/**
* Applies configuration from the provided source to this layer's source,
* and reconfigures the loader to add a feature that renders the background,
* if the style is configured with a background.
* @param {import("../source/VectorTile.js").default} source The source to configure from.
* @param {StyleObject} style The style to configure the background from.
*/
configureSource(source, style) {
const targetSource = this.getSource();
if (source !== targetSource) {
targetSource.setAttributions(source.getAttributions());
targetSource.setTileUrlFunction(source.getTileUrlFunction());
targetSource.setTileLoadFunction(source.getTileLoadFunction());
targetSource.tileGrid = source.tileGrid;
}
if (this.getBackground() === undefined) {
applyBackground(this, style);
applyBackground(this, options.styleUrl, {
accessToken: this.accessToken,
});
}
if (this.setMaxResolutionFromTileGrid_) {
const tileGrid = targetSource.getTileGrid();
this.setMaxResolution(tileGrid.getResolution(tileGrid.getMinZoom()));
}
targetSource.setState(SourceState.READY);
}
/**
* Handle configuration or loading error.
* @param {Error} error The error.
* @protected
*/
handleError(error) {
this.dispatchEvent(new ErrorEvent(error));
const source = this.getSource();
source.setState(SourceState.ERROR);
}
}

View File

@@ -74,6 +74,11 @@ module.exports = function (karma) {
},
module: {
rules: [
{
test: /\.js$/,
enforce: 'pre',
use: ['source-map-loader'],
},
{
test: /\.js$/,
use: {

View File

@@ -1,123 +1,8 @@
import MapboxVectorLayer, {
getMapboxPath,
normalizeSourceUrl,
normalizeSpriteUrl,
normalizeStyleUrl,
} from '../../../../../src/ol/layer/MapboxVector.js';
import MapboxVectorLayer from '../../../../../src/ol/layer/MapboxVector.js';
import {asString} from '../../../../../src/ol/color.js';
import {unByKey} from '../../../../../src/ol/Observable.js';
describe('ol/layer/MapboxVector', () => {
describe('getMapboxPath()', () => {
const cases = [
{
url: 'mapbox://path/to/resource',
expected: 'path/to/resource',
},
{
url: 'mapbox://path/to/resource?query',
expected: 'path/to/resource?query',
},
{
url: 'https://example.com/resource',
expected: '',
},
];
for (const c of cases) {
it(`works for ${c.url}`, () => {
expect(getMapboxPath(c.url)).to.be(c.expected);
});
}
});
describe('normalizeStyleUrl()', () => {
const cases = [
{
url: 'mapbox://styles/mapbox/bright-v9',
expected:
'https://api.mapbox.com/styles/v1/mapbox/bright-v9?&access_token=test-token',
},
{
url: 'https://example.com/style',
expected: 'https://example.com/style',
},
];
const token = 'test-token';
for (const c of cases) {
it(`works for ${c.url}`, () => {
expect(normalizeStyleUrl(c.url, token)).to.be(c.expected);
});
}
});
describe('normalizeSpriteUrl()', () => {
const cases = [
{
url: 'mapbox://sprites/mapbox/bright-v9',
expected:
'https://api.mapbox.com/styles/v1/mapbox/bright-v9/sprite?access_token=test-token',
},
{
url: 'https://example.com/sprite',
expected: 'https://example.com/sprite',
},
{
url: '../sprite',
expected: 'https://example.com:8000/sprite',
},
{
url: '/sprite',
expected: 'https://example.com:8000/sprite',
},
{
url: './sprite',
expected: 'https://example.com:8000/mystyle/sprite',
},
];
const token = 'test-token';
for (const c of cases) {
it(`works for ${c.url}`, () => {
expect(
normalizeSpriteUrl(
c.url,
token,
'https://example.com:8000/mystyle/style.json'
)
).to.be(c.expected);
});
}
});
describe('normalizeSourceUrl()', () => {
const cases = [
{
url: 'mapbox://mapbox.mapbox-streets-v7',
expected:
'https://{a-d}.tiles.mapbox.com/v4/mapbox.mapbox-streets-v7/{z}/{x}/{y}.vector.pbf?access_token=test-token',
},
{
url: 'https://example.com/source/{z}/{x}/{y}.pbf',
expected: 'https://example.com/source/{z}/{x}/{y}.pbf?token=test-token',
},
{
url: 'https://example.com/source/{z}/{x}/{y}.pbf?foo=bar',
expected:
'https://example.com/source/{z}/{x}/{y}.pbf?foo=bar&token=test-token',
},
];
const token = 'test-token';
const tokenParam = 'token';
for (const c of cases) {
it(`works for ${c.url}`, () => {
expect(normalizeSourceUrl(c.url, token, tokenParam)).to.be(c.expected);
});
}
});
describe('TileJSON', function () {
it('lets ol-mapbox-style handle TileJSON URLs', function (done) {
const layer = new MapboxVectorLayer({
@@ -136,6 +21,9 @@ describe('ol/layer/MapboxVector', () => {
})
),
});
layer.on('error', function (e) {
done(e.error);
});
const source = layer.getSource();
const key = source.on('change', function () {
if (source.getState() === 'ready') {
@@ -185,6 +73,9 @@ describe('ol/layer/MapboxVector', () => {
const layer = new MapboxVectorLayer({
styleUrl: styleUrl,
});
layer.on('error', function (e) {
done(e.error);
});
const source = layer.getSource();
source.on('change', function onchange() {
if (source.getState() === 'ready') {
@@ -312,20 +203,31 @@ describe('ol/layer/MapboxVector', () => {
});
describe('Access token', function () {
it('applies correct access token from access_token', function () {
const layer = new MapboxVectorLayer({
let originalFetch, fetchUrl;
beforeEach(function () {
originalFetch = fetch;
window.fetch = function (url) {
fetchUrl = url;
return Promise.resolve();
};
});
afterEach(function () {
window.fetch = originalFetch;
});
it('applies correct access token', function () {
new MapboxVectorLayer({
styleUrl: 'mapbox://styles/mapbox/streets-v7',
accessToken: '123',
});
expect(layer.accessToken).to.be('123');
expect(layer.accessTokenParam_).to.be(undefined);
expect(fetchUrl.url).to.be(
'https://api.mapbox.com/styles/v1/mapbox/streets-v7?&access_token=123'
);
});
it('applies correct access token from url', function () {
const layer = new MapboxVectorLayer({
new MapboxVectorLayer({
styleUrl: 'foo?key=123',
});
expect(layer.accessToken).to.be('123');
expect(layer.accessTokenParam_).to.be('key');
expect(fetchUrl.url).to.be(`${location.origin}/foo?key=123`);
});
});
});