UNPKG

geoportal-extensions-openlayers

Version:

![GitHub package.json version](https://img.shields.io/github/package-json/v/IGNF/geoportal-extensions?filename=build%2Fscripts%2Frelease%2Fpackage-openlayers.json)

374 lines (336 loc) 13 kB
// import openlayers import VectorTileLayer from "ol/layer/VectorTile"; import VectorTileSource from "ol/source/VectorTile"; import TileJSONSource from "ol/source/TileJSON"; import MVT from "ol/format/MVT"; import { unByKey as observableUnByKey } from "ol/Observable"; // import olms : module ES6 import { applyStyle } from "ol-mapbox-style"; // import local import Utils from "../../Common/Utils"; import Config from "../../Common/Utils/Config"; /** * @classdesc * Geoportal Layer Mapbox creation * * @constructor * @extends {ol.layer.VectorTile} * @alias ol.layer.GeoportalMapBox * @type {ol.layer.GeoportalMapBox} * @param {Object} options - options for function call. * @param {String} options.layer - Layer name (e.g. "PLAN.IGN") * @param {String} [options.style] - Style name (e.g. "classique") * @param {String} [options.source] - Source name (e.g. "plan_ign") * @param {Boolean} [options.ssl] - if set true, enforce protocol https (only for nodejs) * @param {Object} [settings] - other options for ol.layer.VectorTile function (see {@link https://openlayers.org/en/latest/apidoc/module-ol_layer_VectorTile-VectorTileLayer.html ol.layer.VectorTile}) * @example * var LayerMapBox = new ol.layer.GeoportalMapBox({ * layer : "PLAN.IGN", * [style : "classique",] * [source : "plan_ign",] * [ssl: true] * }, { * opacity * visible * extent * declutter * ... * }); */ var LayerMapBox = (function (VectorTileLayer) { /** * See {@link ol.layer.GeoportalMapBox} * @module LayerMapBox * @alias module:~Layers/GeoportalMapBox * @param {*} options - options * @param {*} [settings] - other settings * @example * import LayerMapBox from "src/OpenLayers/Layers/LayerMapBox" */ function LayerMapBox (options, settings) { if (!(this instanceof LayerMapBox)) { throw new TypeError("ERROR CLASS_CONSTRUCTOR"); } if (!options.layer) { throw new Error("ERROR PARAM_MISSING : layer"); } if (typeof options.layer !== "string") { throw new Error("ERROR WRONG TYPE : layer"); } this.layerName = options.layer; // autres options facultatives this.styleName = options.style; this.sourceId = options.source; // par defaut if (typeof options.ssl === "undefined") { options.ssl = true; } // si ssl = false on fait du http // par défaut, ssl = true, on fait du https this.protocol = options.ssl === false ? "http://" : "https://"; // WARNING : // on fait le choix de ne pas utiliser la clef apiKey pour checker les droits sur la ressource // car le service n'est pas securisé... // Check if configuration is loaded if (!Config.isConfigLoaded()) { throw new Error("ERROR : contract key configuration has to be loaded to load Geoportal layers."); } /** * Ex. configuration object for TMS Layer * (only for jsdoc) * @example * "PLAN.IGN$GEOPORTAIL:GPP:TMS": { * "hidden": true, * "queryable": false, * "serviceParams": { * "id": "GPP:TMS", * "version": "1.0.0", * "serverUrl": { * "cartes": "https://wxs.ign.fr/cartes/geoportail/tms/1.0.0/" * } * }, * "name": "PLAN.IGN", * "title": "Plan IGN", * "description": "BDUni tuilée", * "formats": [ * { * "current": true, * "name": "application/x-protobuf" * } * ], * "styles": [ * { * "name": "standard", * "title": "Style standard", * "current": true, * "url": "https://wxs.ign.fr/static/vectorTiles/styles/PLAN.IGN/essentiels/standard.json" * }, * { * "name": "classique", * "title": "Style classique", * "current": true, * "url": "https://wxs.ign.fr/static/vectorTiles/styles/PLAN.IGN/essentiels/classique.json" * }, * { * "name": "transparent", * "title": "Style transparent", * "current": true, * "url": "https://wxs.ign.fr/static/vectorTiles/styles/PLAN.IGN/essentiels/transparent.json" * }, * { * "name": "accentue", * "title": "Style accentue", * "current": true, * "url": "https://wxs.ign.fr/static/vectorTiles/styles/PLAN.IGN/essentiels/accentue.json" * }, * { * "name": "attenue", * "title": "Style attenue", * "current": true, * "url": "https://wxs.ign.fr/static/vectorTiles/styles/PLAN.IGN/essentiels/attenue.json" * }, * { * "name": "gris", * "title": "Style en noir et blanc", * "current": false, * "url": "https://wxs.ign.fr/static/vectorTiles/styles/PLAN.IGN/essentiels/gris.json" * }, * { * "name": "epure", * "title": "Style epure", * "current": true, * "url": "https://wxs.ign.fr/static/vectorTiles/styles/PLAN.IGN/essentiels/epure.json" * }, * { * "name": "sans_toponymes", * "title": "Style sans toponymes", * "current": false, * "url": "https://wxs.ign.fr/static/vectorTiles/styles/PLAN.IGN/essentiels/sans_toponymes.json" * } * ], * "globalConstraint": { * "crs": null, * "bbox": { * "left": -724011.531917197, * "right": 1095801.237496279, * "top": 6672646.821182753, * "bottom": 5009377.0856973175 * }, * "minScaleDenominator": null, * "maxScaleDenominator": null * }, * "quicklookUrl": "https://wxs.ign.fr/static/pictures/ign_carte2.jpg", * "layerId": "PLAN.IGN$GEOPORTAIL:GPP:TMS", * "defaultProjection": "EPSG:3857" * } */ // récupération des ressources utiles depuis la configuration var layerId = this.layerName + "$GEOPORTAIL:GPP:TMS"; var layerCfg = Config.configuration.getLayerConf(layerId); if (!layerCfg) { throw new Error("ERROR : Layer ID not found into the catalogue !?"); } this.styleUrl = null; this.styleTitle = ""; for (var i = 0; i < layerCfg.styles.length; i++) { var style = layerCfg.styles[i]; // si le nom du style est en option, on le recherche... // sinon, on recherche le style par defaut ! if (this.styleName && style.name === this.styleName) { this.styleUrl = style.url; this.styleTitle = style.title; break; } else { if (!this.styleName && style.current) { this.styleName = style.name; this.styleUrl = style.url; this.styleTitle = style.title; break; } } } if (!this.styleUrl) { throw new Error("ERROR : Style URL not found !?"); } this.styleUrl.replace(/(http|https):\/\//, this.protocol); // création de la source var source = new VectorTileSource({ state : "loading", // statut format : new MVT() }); source._originators = layerCfg.originators; source._legends = layerCfg.legends; source._metadata = layerCfg.metadata; source._description = layerCfg.description; source._title = layerCfg.title + " (" + this.styleTitle + ")"; source._quicklookUrl = layerCfg.quicklookUrl; // options definies sur ol.layer.VectorTile var layerVectorTileOptions = { source : source }; // récupération des autres paramètres passés par l'utilisateur Utils.mergeParams(layerVectorTileOptions, settings); // création d'une ol.layer.VectorTile avec les options récupérées ci-dessus. VectorTileLayer.call(this, layerVectorTileOptions); // on surcharge les originators (non récupérés depuis configuration de la couche) if (options.olParams && !layerCfg.originators) { source._originators = options.olParams.attributions; } // add originators to layer source (to be updated by Originators control) this._originators = source.originators; // récuperation du style this.setStyleMapBox(); } // Inherits from ol.layer.VectorTile if (VectorTileLayer) LayerMapBox.__proto__ = VectorTileLayer; /* * @lends module:LayerMapBox */ LayerMapBox.prototype = Object.create(VectorTileLayer.prototype, {}); /* * Constructor (alias) */ LayerMapBox.prototype.constructor = LayerMapBox; /** * Get Style MapBox * @private */ LayerMapBox.prototype.setStyleMapBox = function () { var self = this; fetch(this.styleUrl, { credentials : "same-origin" }) .then(function (response) { if (response.ok) { response.json().then(function (style) { self.onStyleMapBoxLoad(style); }); } }) .catch(function (e) { self.onStyleMapBoxError(e); }); }; /** * Add Style * @param {*} style - json style */ LayerMapBox.prototype.onStyleMapBoxLoad = function (style) { // si on a plusieurs sources, on ne peut en prendre qu'une seule... if (!this.sourceId) { this.sourceId = Object.keys(style.sources)[0]; } var styleSource = style.sources[this.sourceId]; if (!styleSource) { this.onStyleMapBoxError({ message : "ERROR : Source ID not found !? !" }); return; } if (styleSource.type !== "vector") { this.onStyleMapBoxError({ message : "ERROR : Source TYPE not permitted !" }); return; } var source = this.getSource(); // WARNING : // la clef renseignée dans les urls n'est pas forcement la bonne // car la substitution avec la clef utilisateur n'est pas faite par le service... if (styleSource.url) { // protocole : http ou https styleSource.url.replace(/(http|https):\/\//, this.protocol); var vectorTileJson = new TileJSONSource({ url : styleSource.url }); var self = this; var key = vectorTileJson.on("change", function () { if (vectorTileJson.getState() === "ready") { var doc = vectorTileJson.getTileJSON(); if (!doc) { return; } self.set("mapbox-extensions", doc); var tiles = Array.isArray(doc.tiles) ? doc.tiles : [doc.tiles]; // protocole : http ou https for (var i = 0; i < styleSource.tiles.length; i++) { tiles[i].replace(/(http|https):\/\//, this.protocol); } source.setUrls(tiles); observableUnByKey(key); } }); } if (styleSource.tiles) { // protocole : http ou https for (var j = 0; j < styleSource.tiles.length; j++) { styleSource.tiles[j].replace(/(http|https):\/\//, this.protocol); } source.setUrls(styleSource.tiles); } applyStyle(this, style, this.sourceId) .then(() => { source.setState("ready"); this.set("mapbox-styles", style); }) .catch((error) => { this.onStyleMapBoxError(error); }); }; /** * Error * @param {*} error - message */ LayerMapBox.prototype.onStyleMapBoxError = function (error) { var source = this.getSource(); source.setState("error"); // eslint-disable-next-line no-console console.error(error.message); }; return LayerMapBox; }(VectorTileLayer)); export default LayerMapBox; // Expose LayerMapBox as ol.layer.GeoportalMapBox. (for a build bundle) if (window.ol && window.ol.layer) { window.ol.layer.GeoportalMapBox = LayerMapBox; }