-
Notifications
You must be signed in to change notification settings - Fork 179
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature: add layer control to map viewer html template (#1051)
* make placemarks toggleable with a button or the 'b' key --------- Co-authored-by: Vincent Sarago <[email protected]>
- Loading branch information
1 parent
4937dfa
commit fb1bb1e
Showing
2 changed files
with
223 additions
and
140 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,146 +1,226 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset='utf-8' /> | ||
<title>TiTiler Map Viewer</title> | ||
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' /> | ||
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" | ||
integrity="sha384-o/2yZuJZWGJ4s/adjxVW71R+EO/LyCwdQfP5UWSgX/w87iiTXuvDZaejd3TsN7mf" | ||
crossorigin="anonymous"/> | ||
<script src="https://unpkg.com/[email protected]/dist/leaflet.js" | ||
integrity="sha384-okbbMvvx/qfQkmiQKfd5VifbKZ/W8p1qIsWvE1ROPUfHWsDcC8/BnHohF7vPg2T6" | ||
crossorigin="anonymous"></script> | ||
<script src="https://unpkg.com/[email protected]/dist/proj4.js" | ||
integrity="sha384-R7x++v2MKcATI+D1/GJsn636xbHca492Sdpm8BD36lj5vdWB9+OUBpM1oKkrzqv9" | ||
crossorigin="anonymous"></script> | ||
<script src="https://unpkg.com/[email protected]/src/proj4leaflet.js" | ||
integrity="sha384-aDnBHDK9AhLbrYhThBxEVMriFbix8Sz2059IlD3HbZhz7+WNmz+pSkOcI7MY72cE" | ||
crossorigin="anonymous"></script> | ||
<style> | ||
body { margin:0; padding:0; width:100%; height:100%; background-color: #e5e5e5;} | ||
#map { position:absolute; top:0; bottom:0; width:100%; } | ||
</style> | ||
</head> | ||
<body> | ||
|
||
<div id='map'></div> | ||
<!doctype html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<title>TiTiler Map Viewer</title> | ||
<meta | ||
name="viewport" | ||
content="initial-scale=1,maximum-scale=1,user-scalable=no" | ||
/> | ||
<link | ||
rel="stylesheet" | ||
href="https://unpkg.com/[email protected]/dist/leaflet.css" | ||
integrity="sha384-o/2yZuJZWGJ4s/adjxVW71R+EO/LyCwdQfP5UWSgX/w87iiTXuvDZaejd3TsN7mf" | ||
crossorigin="anonymous" | ||
/> | ||
<script | ||
src="https://unpkg.com/[email protected]/dist/leaflet.js" | ||
integrity="sha384-okbbMvvx/qfQkmiQKfd5VifbKZ/W8p1qIsWvE1ROPUfHWsDcC8/BnHohF7vPg2T6" | ||
crossorigin="anonymous" | ||
></script> | ||
<script | ||
src="https://unpkg.com/[email protected]/dist/proj4.js" | ||
integrity="sha384-R7x++v2MKcATI+D1/GJsn636xbHca492Sdpm8BD36lj5vdWB9+OUBpM1oKkrzqv9" | ||
crossorigin="anonymous" | ||
></script> | ||
<script | ||
src="https://unpkg.com/[email protected]/src/proj4leaflet.js" | ||
integrity="sha384-aDnBHDK9AhLbrYhThBxEVMriFbix8Sz2059IlD3HbZhz7+WNmz+pSkOcI7MY72cE" | ||
crossorigin="anonymous" | ||
></script> | ||
<style> | ||
body { | ||
margin: 0; | ||
padding: 0; | ||
width: 100%; | ||
height: 100%; | ||
background-color: #e5e5e5; | ||
} | ||
#map { | ||
position: absolute; | ||
top: 0; | ||
bottom: 0; | ||
width: 100%; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<div id="map"></div> | ||
|
||
<script type="text/javascript"> | ||
|
||
const bboxPolygon = (bounds) => { | ||
var LL_EPSILON = 1e-6 | ||
return { | ||
'type': 'Feature', | ||
'geometry': { | ||
'type': 'Polygon', | ||
'coordinates': [[ | ||
[bounds[0] + LL_EPSILON, bounds[1] + LL_EPSILON], | ||
[bounds[2] - LL_EPSILON, bounds[1] + LL_EPSILON], | ||
[bounds[2] - LL_EPSILON, bounds[3] - LL_EPSILON], | ||
[bounds[0] + LL_EPSILON, bounds[3] - LL_EPSILON], | ||
[bounds[0] + LL_EPSILON, bounds[1] + LL_EPSILON] | ||
]] | ||
}, | ||
'properties': {} | ||
} | ||
} | ||
|
||
var crs = new L.Proj.CRS( | ||
'{{ tms.crs.srs }}', | ||
'{{ tms.crs.to_proj4() }}', { | ||
origin: [{{ tms.xy_bbox.left }}, {{ tms.xy_bbox.top }}], | ||
bounds: L.bounds( | ||
L.Point({{ tms.xy_bbox.left}}, {{ tms.xy_bbox.bottom }}), | ||
L.Point({{ tms.xy_bbox.right}}, {{ tms.xy_bbox.top }}) | ||
), | ||
resolutions: {{ resolutions|safe }}, | ||
} | ||
); | ||
|
||
|
||
var map = L.map('map', { | ||
crs: crs, | ||
minZoom: {{ tms.minzoom }}, | ||
maxZoom: {{ tms.maxzoom }}, | ||
attributionControl: false | ||
}); | ||
|
||
L.control.attribution({prefix: '<a href="https://leafletjs.com" target="_blank">Leaflet</a> | <a href="https://developmentseed.org/titiler" target="_blank">Titiler</a>'}).addTo(map) | ||
|
||
const nullIsland = L.marker([0, 0]).addTo(map); | ||
const madrid = L.marker([40, -3]).addTo(map); | ||
const london = L.marker([51.50722, -0.1275]).addTo(map) | ||
const auckland = L.marker([-36.864664, 174.792059]).addTo(map); | ||
const seattle = L.marker([47.596842, -122.333087]).addTo(map); | ||
|
||
if ("{{ tms.id }}" === "WebMercatorQuad") { | ||
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { | ||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' | ||
}).addTo(map); | ||
} | ||
|
||
fetch('{{ tilejson_endpoint|safe }}') | ||
.then(res => { | ||
if (res.ok) return res.json() | ||
throw new Error('Network response was not ok.') | ||
}) | ||
.then(data => { | ||
console.log(data) | ||
|
||
let bounds = [...data.bounds] | ||
|
||
var left = bounds[0], | ||
bottom = bounds[1], | ||
right = bounds[2], | ||
top = bounds[3]; | ||
|
||
if (left < right) { | ||
left = Math.max(left, {{ tms.bbox.left }}) | ||
right = Math.min(right, {{ tms.bbox.right }}) | ||
} | ||
bottom = Math.max(bottom, {{ tms.bbox.bottom }}) | ||
top = Math.min(top, {{ tms.bbox.top }}) | ||
console.log(left, bottom, right, top) | ||
|
||
let geo; | ||
// handle files that span accross dateline | ||
if (left > right) { | ||
geo = { | ||
"type": "FeatureCollection", | ||
"features": [ | ||
bboxPolygon([-180, bottom, right, top]), | ||
bboxPolygon([left, bottom, 180, top]), | ||
] | ||
} | ||
} else { | ||
geo = { | ||
"type": "FeatureCollection", | ||
"features": [bboxPolygon([left, bottom, right, top])] | ||
const bboxPolygon = (bounds) => { | ||
var LL_EPSILON = 1e-6 | ||
return { | ||
'type': 'Feature', | ||
'geometry': { | ||
'type': 'Polygon', | ||
'coordinates': [[ | ||
[bounds[0] + LL_EPSILON, bounds[1] + LL_EPSILON], | ||
[bounds[2] - LL_EPSILON, bounds[1] + LL_EPSILON], | ||
[bounds[2] - LL_EPSILON, bounds[3] - LL_EPSILON], | ||
[bounds[0] + LL_EPSILON, bounds[3] - LL_EPSILON], | ||
[bounds[0] + LL_EPSILON, bounds[1] + LL_EPSILON] | ||
]] | ||
}, | ||
'properties': {} | ||
} | ||
} | ||
} | ||
console.log(geo) | ||
|
||
var aoi = L.geoJSON(geo, { | ||
color: '#3bb2d0', fill: false | ||
}).addTo(map); | ||
map.fitBounds(aoi.getBounds()); | ||
|
||
// Bounds crossing dateline | ||
if (left > right) { | ||
left = right - 360 | ||
} | ||
|
||
L.tileLayer( | ||
data.tiles[0], { | ||
maxNativeZoom: data.maxzoom, | ||
minNativeZoom: data.minzoom, | ||
bounds: L.latLngBounds([bottom, left], [top, right]), | ||
|
||
var crs = new L.Proj.CRS( | ||
'{{ tms.crs.srs }}', | ||
'{{ tms.crs.to_proj4() }}', { | ||
origin: [{{ tms.xy_bbox.left }}, {{ tms.xy_bbox.top }}], | ||
bounds: L.bounds( | ||
L.Point({{ tms.xy_bbox.left}}, {{ tms.xy_bbox.bottom }}), | ||
L.Point({{ tms.xy_bbox.right}}, {{ tms.xy_bbox.top }}) | ||
), | ||
resolutions: {{ resolutions|safe }}, | ||
} | ||
); | ||
|
||
|
||
var map = L.map('map', { | ||
crs: crs, | ||
minZoom: {{ tms.minzoom }}, | ||
maxZoom: {{ tms.maxzoom }}, | ||
attributionControl: false | ||
}); | ||
|
||
L.control.attribution({prefix: '<a href="https://leafletjs.com" target="_blank">Leaflet</a> | <a href="https://developmentseed.org/titiler" target="_blank">Titiler</a>'}).addTo(map) | ||
|
||
let baseLayers = {}; | ||
let overlayLayers = {}; | ||
let activeBaseLayer = null; | ||
|
||
if ("{{ tms.id }}" === "WebMercatorQuad") { | ||
|
||
const esriSatelliteLayer = L.tileLayer( | ||
'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', { | ||
attribution: 'Tiles © ESRI — Source: Esri, DigitalGlobe, GeoEye, i-cubed, USDA FSA, USGS, AEX, Getmapping, Aerogrid, IGN, IGP, swisstopo, and the GIS User Community', | ||
maxZoom: 19 | ||
} | ||
); | ||
esriSatelliteLayer.addTo(map); | ||
baseLayers["Esri Satellite"] = esriSatelliteLayer; | ||
|
||
const osmLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { | ||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>' | ||
}); | ||
osmLayer.addTo(map); | ||
baseLayers["OpenStreetMap"] = osmLayer; | ||
activeBaseLayer = osmLayer; | ||
} | ||
).addTo(map); | ||
}) | ||
.catch(err => { | ||
console.warn(err) | ||
}) | ||
|
||
// Add some placemarks for use in validating display with custom TMS | ||
var nullIsland = L.marker([0, 0]), | ||
madrid = L.marker([40, -3]), | ||
london = L.marker([51.50722, -0.1275]), | ||
auckland = L.marker([-36.864664, 174.792059]), | ||
seattle = L.marker([47.596842, -122.333087]); | ||
|
||
var cities = L.layerGroup([nullIsland, london, auckland, seattle]); | ||
|
||
document.addEventListener('keydown', function(e) { | ||
if (e.key === 'b' || e.key === 'B') { | ||
if (map.hasLayer(cities)) { | ||
map.removeLayer(cities); | ||
} else { | ||
map.addLayer(cities); | ||
} | ||
} | ||
}); | ||
|
||
const toggleButton = L.control({position: 'bottomright'}); | ||
toggleButton.onAdd = function(map) { | ||
const div = L.DomUtil.create('div', 'toggle-cities'); | ||
div.innerHTML = ` | ||
<button style=" | ||
font-size: 10px; | ||
padding: 2px 5px; | ||
background: rgba(255, 255, 255, 0.8); | ||
border: 1px solid #ccc; | ||
border-radius: 3px; | ||
cursor: pointer; | ||
">⚲</button> | ||
`; | ||
div.onclick = function() { | ||
if (map.hasLayer(cities)) { | ||
map.removeLayer(cities); | ||
} else { | ||
map.addLayer(cities); | ||
} | ||
}; | ||
return div; | ||
}; | ||
toggleButton.addTo(map); | ||
|
||
// Add the tile layer! | ||
fetch('{{ tilejson_endpoint|safe }}') | ||
.then(res => { | ||
if (res.ok) return res.json() | ||
throw new Error('Network response was not ok.') | ||
}) | ||
.then(data => { | ||
console.log(data); | ||
|
||
let bounds = [...data.bounds]; | ||
|
||
var left = bounds[0], | ||
bottom = bounds[1], | ||
right = bounds[2], | ||
top = bounds[3]; | ||
|
||
if (left < right) { | ||
left = Math.max(left, {{ tms.bbox.left }}); | ||
right = Math.min(right, {{ tms.bbox.right }}); | ||
} | ||
bottom = Math.max(bottom, {{ tms.bbox.bottom }}); | ||
top = Math.min(top, {{ tms.bbox.top }}); | ||
|
||
let geo; | ||
if (left > right) { | ||
geo = { | ||
"type": "FeatureCollection", | ||
"features": [ | ||
bboxPolygon([-180, bottom, right, top]), | ||
bboxPolygon([left, bottom, 180, top]), | ||
] | ||
}; | ||
} else { | ||
geo = { | ||
"type": "FeatureCollection", | ||
"features": [bboxPolygon([left, bottom, right, top])] | ||
}; | ||
} | ||
|
||
var aoi = L.geoJSON(geo, { | ||
color: '#3bb2d0', fill: false | ||
}).addTo(map); | ||
map.fitBounds(aoi.getBounds()); | ||
|
||
if (left > right) { | ||
left = right - 360; | ||
} | ||
|
||
const tileLayer = L.tileLayer( | ||
data.tiles[0], { | ||
maxNativeZoom: data.maxzoom, | ||
minNativeZoom: data.minzoom, | ||
bounds: L.latLngBounds([bottom, left], [top, right]), | ||
} | ||
); | ||
|
||
overlayLayers["TiTiler Layer"] = tileLayer; | ||
|
||
tileLayer.addTo(map); | ||
|
||
// Add L.control.layers with base and overlay layers | ||
L.control.layers(baseLayers, overlayLayers, {collapsed: false}).addTo(map); | ||
}) | ||
.catch(err => { | ||
console.warn(err); | ||
}); | ||
</script> | ||
</body> | ||
</html> | ||
</body> | ||
</html> |