Commit df1e7f74 authored by Adrien Pavie's avatar Adrien Pavie
Browse files

Better WMTS support, only show most pertinent background tiles

parent 1db69b4b
......@@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- In API, list of background imagery can be stored locally
### Changed
- List of available background imagery is limited to most pertinent ones
- List of available background imagery is limited to most pertinent ones, and shows only 3 by default (aerial imagery, OSM, OSM black & white)
### Fixed
- Geometry sorted by date
......
......@@ -7,7 +7,7 @@
"start": "npm run build && node src/index.js",
"start:prod": "npm run build && while [ true ]; do node src/index.js; sleep 5; done",
"build": "npm run build:assets && npm run build:js",
"build:assets": "mkdir -p build && cp -r src/website/*.html src/website/*.css src/website/img node_modules/bootstrap/dist/css/bootstrap.min.css node_modules/bootstrap/dist/js/bootstrap.min.js node_modules/jquery-slim/dist/jquery.slim.min.js node_modules/leaflet/dist/leaflet.js node_modules/leaflet/dist/leaflet.css node_modules/leaflet-hash/leaflet-hash.js node_modules/font-awesome/css/font-awesome.min.css node_modules/font-awesome/fonts node_modules/qrcode-svg/dist/qrcode.min.js node_modules/leaflet-bing-layer/leaflet-bing-layer.min.js node_modules/leaflet.locatecontrol/dist/L.Control.Locate.min.css node_modules/leaflet.locatecontrol/dist/L.Control.Locate.min.js build/",
"build:assets": "mkdir -p build && cp -r src/website/*.html src/website/*.css src/website/img node_modules/bootstrap/dist/css/bootstrap.min.css node_modules/bootstrap/dist/js/bootstrap.min.js node_modules/jquery-slim/dist/jquery.slim.min.js node_modules/leaflet/dist/leaflet.js node_modules/leaflet/dist/leaflet.css node_modules/leaflet-hash/leaflet-hash.js node_modules/font-awesome/css/font-awesome.min.css node_modules/font-awesome/fonts node_modules/qrcode-svg/dist/qrcode.min.js node_modules/leaflet-bing-layer/leaflet-bing-layer.min.js node_modules/leaflet.locatecontrol/dist/L.Control.Locate.min.css node_modules/leaflet.locatecontrol/dist/L.Control.Locate.min.js src/website/lib/*.js build/",
"build:js": "simplifyify --minify --outfile \"build/*.min.js\" src/website/*.js",
"clean": "rm -rf ./build",
"i18n:build": "i18nline synch",
......
......@@ -37,7 +37,9 @@ const fixCategory = { "Bing": "photo", "fr.ign.bdortho": "photo" };
function parseSaveBackgroundLayers(geojson) {
const toKeep = geojson.features.filter(layer => {
const p = layer.properties;
p.type = p.type || fixCategory[p.id] || "other";
p.category = p.category || fixCategory[p.id] || "other";
if(p.category === "other" && p.name.toLowerCase().includes("aerial")) { p.category = "photo"; }
return p.id && p.url && p.name
&& !exclusionList.includes(p.id)
&& ["tms", "wms", "bing", "wmts"].includes(p.type)
......@@ -60,11 +62,13 @@ function parseSaveBackgroundLayers(geojson) {
attribution = `<a href="${p.attribution.url}" target="_blank">${attribution || "License"}</a>`;
}
let wmsParams = p.type === "wms" ? {} : null;
return {
id: p.id,
name: p.name,
type: p.type,
category: fixCategory[p.id] || p.category || "other",
category: p.category,
url: p.url
.replace(/{zoom}/g, '{z}')
.replace(/{switch:.+?}/g, '{s}'),
......@@ -74,7 +78,8 @@ function parseSaveBackgroundLayers(geojson) {
minZoom: p.min_zoom || 0,
maxZoom: p.max_zoom || 18,
subdomains: subdomains,
end_date: p.end_date || Date.now()
wmsParams: wmsParams,
end_date: p.end_date || (new Date()).toISOString().split("Z")[0]
};
});
......@@ -160,7 +165,7 @@ io.on("connection", socket => {
const [ cat, layers ] = e;
layers.sort((a, b) => {
if(a.best || b.best) {
return a.best ? -1 : 1;
return a.best ? (b.best ? 0 : -1) : 1;
}
else {
return (new Date(a.end_date)).getTime() - (new Date(b.end_date)).getTime();
......
......@@ -15,6 +15,7 @@
"medium_5a8e9ead": "Medium",
"menu_39cb0e8e": "Menu",
"meters_b16f9ec4": "meters",
"more_cf9cc661": "More",
"no_result_for_your_search_please_check_given_addre_f7a680e1": "No result for your search, please check given address.",
"search_280d00bd": "Search",
"search_service_is_unavailable_please_retry_later_19aef6cc": "Search service is unavailable. Please retry later.",
......
......@@ -15,6 +15,7 @@
"medium_5a8e9ead": "Medium",
"menu_39cb0e8e": "Menu",
"meters_b16f9ec4": "meters",
"more_cf9cc661": "More",
"no_result_for_your_search_please_check_given_addre_f7a680e1": "No result for your search, please check given address.",
"search_280d00bd": "Search",
"search_service_is_unavailable_please_retry_later_19aef6cc": "Search service is unavailable. Please retry later.",
......
......@@ -15,6 +15,7 @@
"medium_5a8e9ead": "Intermédiaire",
"menu_39cb0e8e": "Menu",
"meters_b16f9ec4": "mètres",
"more_cf9cc661": "Plus",
"no_result_for_your_search_please_check_given_addre_f7a680e1": "Aucun résultat trouvé, vérifiez l'adresse saisie.",
"search_280d00bd": "Rechercher",
"search_service_is_unavailable_please_retry_later_19aef6cc": "Le moteur de recherche est indisponible. Merci de réessayer plus tard.",
......
......@@ -160,7 +160,12 @@
<span aria-hidden="true">&times;</span>
</button>
</div>
<div id="background-picker" class="modal-body d-flex flex-wrap justify-content-center">
<div class="modal-body">
<div id="background-picker" class="d-flex flex-wrap justify-content-center">
</div>
<button id="more-bg" class="btn btn-light btn-block d-none">
<i class="fa fa-caret-down" title="More" data-i18n-title="more"></i>
</a>
</div>
</div>
</div>
......@@ -172,6 +177,7 @@
<script src="leaflet-hash.js"></script>
<script src="qrcode.min.js"></script>
<script src="leaflet-bing-layer.min.js"></script>
<script src="leaflet-tilelayer-wmts.js"></script>
<script src="L.Control.Locate.min.js"></script>
<script src="socket.io/socket.io.js"></script>
<script src="index.min.js"></script>
......
......@@ -39,6 +39,7 @@ const domBtnShare = document.getElementById("btn-partageur");
const domBtnShareUrl = document.getElementById("btn-partageur-url");
const domSearchAddress = document.getElementById("searchbar");
const domBackgroundPicker = document.getElementById("background-picker");
const domBackgroundPickerMore = document.getElementById("more-bg");
// I18n
let locale = null;
......@@ -247,17 +248,18 @@ function listenAPIChanges() {
// Callback after background search
socket.on("background_found", layers => {
backgroundLayers = layers.sort((a,b) => {
const diffCat = b.category.localeCompare(a.category);
if(diffCat === 0) {
if(a.best && b.best) { return 0; }
else if(a.best && !b.best) { return -1; }
else { return 1; }
}
else {
return diffCat;
}
});
// Put best background first
let newBgLayers = [];
newBgLayers.push(layers.find(layer => layer.category === "photo") || { empty: true });
newBgLayers.push(layers.find(layer => layer.id === "MAPNIK") || { empty: true });
newBgLayers.push(layers.find(layer => layer.id === "osm-mapnik-black_and_white") || { empty: true });
newBgLayers = newBgLayers.filter(layer => !layer.empty);
// Then add other sorted
layers.filter(layer => !newBgLayers.includes(layer))
.forEach(layer => newBgLayers.push(layer));
backgroundLayers = newBgLayers;
if(useBackgroundFromURL) {
const tile = backgroundLayers.find(bl => bl.id === useBackgroundFromURL);
......@@ -606,9 +608,11 @@ function showTiles(tile) {
tilesLayer = L.tileLayer(tile.url, tile);
break;
case "wms":
case "wmts":
tilesLayer = L.tileLayer.wms(tile.url, tile);
break;
case "wmts":
tilesLayer = new L.TileLayer.WMTS(tile.url, tile);
break;
case "bing":
tilesLayer = L.tileLayer.bing(BING_API_KEY);
break;
......@@ -654,9 +658,10 @@ function updateBackgroundsList() {
domBackgroundPicker.innerHTML = '';
// Create entry for each tile
backgroundLayers.forEach(layer => {
backgroundLayers.forEach((layer, i) => {
const domBgl = document.createElement("div");
domBgl.classList.add("card");
domBgl.classList.add("card", "card-bg");
if(i >= 3) { domBgl.classList.add("d-none"); }
domBgl.setAttribute("data-dismiss", "modal");
if(layer.id === selectedBackgroundLayer) {
domBgl.classList.add("card-selected");
......@@ -691,6 +696,10 @@ function updateBackgroundsList() {
// Click event
domBgl.addEventListener("click", () => showTiles(layer));
});
if(backgroundLayers.length > 3) {
domBackgroundPickerMore.classList.remove("d-none");
}
}
}
......@@ -762,6 +771,10 @@ function init() {
document.getElementById("btn-edit").addEventListener("click", () => changeMode("draw"));
domBtnShare.addEventListener("click", showShareModal);
domBtnUndo.addEventListener("click", undoShapeDrawn);
domBackgroundPickerMore.addEventListener("click", e => {
document.querySelectorAll(".card-bg.d-none").forEach(d => d.classList.remove("d-none"));
domBackgroundPickerMore.classList.add("d-none");
});
$("#backgroundModal").on("show.bs.modal", updateBackgroundsList);
domBtnShareUrl.addEventListener("click", e => {
// Copy text to clipboard
......@@ -842,7 +855,7 @@ function init() {
boxZoom: false
});
map.attributionControl.setPrefix(null);
map.attributionControl.setPrefix("Gribrouillon");
map.addHash();
noStartLocation = location.hash === "#1/0/0";
if(location.hash.length === 0 || !/^#\d+\/-?\d+(\.\d+)?\/-?\d+(\.\d+)?$/.test(location.hash)) {
......@@ -889,6 +902,7 @@ function init() {
document.querySelector("[data-i18n-title='medium']").title = I18n.t("Medium");
document.querySelector("[data-i18n-title='large']").title = I18n.t("Large");
document.querySelector("[data-i18n-title='undo']").title = I18n.t("Undo");
document.querySelector("[data-i18n-title='more']").title = I18n.t("More");
document.querySelector("[data-i18n-title='startdrawing']").title = I18n.t("Start drawing");
document.querySelector("[data-i18n-title='stopdrawing']").title = I18n.t("Stop drawing");
document.querySelector("[data-i18n-title='copy']").title = I18n.t("Copy");
......
L.TileLayer.WMTS=L.TileLayer.extend({defaultWmtsParams:{service:"WMTS",request:"GetTile",version:"1.0.0",layer:"",style:"",tilematrixset:"",format:"image/jpeg"},initialize:function(a,b){this._url=a;var c={},d=Object.keys(b);d.forEach(a=>{c[a.toLowerCase()]=b[a]});var e=L.extend({},this.defaultWmtsParams),f=c.tileSize||this.options.tileSize;for(var g in e.width=c.detectRetina&&L.Browser.retina?e.height=2*f:e.height=f,c)e.hasOwnProperty(g)&&"matrixIds"!=g&&(e[g]=c[g]);this.wmtsParams=e,this.matrixIds=b.matrixIds||this.getDefaultMatrix(),L.setOptions(this,b)},onAdd:function(a){this._crs=this.options.crs||a.options.crs,L.TileLayer.prototype.onAdd.call(this,a)},getTileUrl:function(a){var b=this.options.tileSize,c=a.multiplyBy(b);c.x+=1,c.y-=1;var d=c.add(new L.Point(b,b)),e=this._tileZoom,f=this._crs.project(this._map.unproject(c,e)),g=this._crs.project(this._map.unproject(d,e));tilewidth=g.x-f.x;var h=this.matrixIds[e].identifier,i=this.wmtsParams.tilematrixset+":"+h,j=this.matrixIds[e].topLeftCorner.lng,k=this.matrixIds[e].topLeftCorner.lat,l=Math.floor((f.x-j)/tilewidth),m=-Math.floor((f.y-k)/tilewidth),n=L.Util.template(this._url,{s:this._getSubdomain(a)});return n+L.Util.getParamString(this.wmtsParams,n)+"&tilematrix="+i+"&tilerow="+m+"&tilecol="+l},setParams:function(a,b){return L.extend(this.wmtsParams,a),b||this.redraw(),this},getDefaultMatrix:function(){for(var a=Array(22),b=0;22>b;b++)a[b]={identifier:""+b,topLeftCorner:new L.LatLng(20037508.3428,-20037508.3428)};return a}}),L.tileLayer.wmts=function(a,b){return new L.TileLayer.WMTS(a,b)};
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment