add terrain preview and elevation link
This commit is contained in:
parent
760653901e
commit
f60de38304
5 changed files with 132 additions and 56 deletions
|
@ -114,7 +114,7 @@ section {
|
|||
}
|
||||
.details h3 {
|
||||
font-size: 18px;
|
||||
margin-top: 25px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
.details p {
|
||||
padding: 0;
|
||||
|
|
|
@ -4,20 +4,25 @@
|
|||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{name}} - TileServer GL</title>
|
||||
{{#is_vector}}
|
||||
{{#use_maplibre}}
|
||||
<link rel="stylesheet" type="text/css" href="{{public_url}}maplibre-gl.css{{&key_query}}" />
|
||||
<link rel="stylesheet" type="text/css" href="{{public_url}}maplibre-gl-inspect.css{{&key_query}}" />
|
||||
<script src="{{public_url}}maplibre-gl.js{{&key_query}}"></script>
|
||||
<script src="{{public_url}}maplibre-gl-inspect.js{{&key_query}}"></script>
|
||||
<style>
|
||||
body {background:#fff;color:#333;font-family:Arial, sans-serif;}
|
||||
{{^is_terrain}}
|
||||
#map {position:absolute;top:0;left:0;right:250px;bottom:0;}
|
||||
{{/is_terrain}}
|
||||
{{#is_terrain}}
|
||||
#map { position:absolute; top:0; bottom:0; width:100%; }
|
||||
{{/is_terrain}}
|
||||
h1 {position:absolute;top:5px;right:0;width:240px;margin:0;line-height:20px;font-size:20px;}
|
||||
#layerList {position:absolute;top:35px;right:0;bottom:0;width:240px;overflow:auto;}
|
||||
#layerList div div {width:15px;height:15px;display:inline-block;}
|
||||
</style>
|
||||
{{/is_vector}}
|
||||
{{^is_vector}}
|
||||
{{/use_maplibre}}
|
||||
{{^use_maplibre}}
|
||||
<link rel="stylesheet" type="text/css" href="{{public_url}}leaflet.css{{&key_query}}" />
|
||||
<script src="{{public_url}}leaflet.js{{&key_query}}"></script>
|
||||
<script src="{{public_url}}leaflet-hash.js{{&key_query}}"></script>
|
||||
|
@ -37,23 +42,22 @@
|
|||
background-image: url({{public_url}}images/marker-icon.png{{&key_query}});
|
||||
}
|
||||
</style>
|
||||
{{/is_vector}}
|
||||
{{/use_maplibre}}
|
||||
</head>
|
||||
<body>
|
||||
{{#is_vector}}
|
||||
{{#use_maplibre}}
|
||||
<h1>{{name}}</h1>
|
||||
<div id="map"></div>
|
||||
{{^is_terrain}}
|
||||
<div id="layerList"></div>
|
||||
<pre id="propertyList"></pre>
|
||||
{{/is_terrain}}
|
||||
<script>
|
||||
var keyMatch = location.search.match(/[\?\&]key=([^&]+)/i);
|
||||
var keyParam = keyMatch ? '?key=' + keyMatch[1] : '';
|
||||
var keyMatch = location.search.match(/[\?\&]key=([^&]+)/i);
|
||||
var keyParam = keyMatch ? '?key=' + keyMatch[1] : '';
|
||||
|
||||
var map = new maplibregl.Map({
|
||||
container: 'map',
|
||||
hash: true,
|
||||
maxPitch: 85,
|
||||
style: {
|
||||
{{^is_terrain}}
|
||||
var style = {
|
||||
version: 8,
|
||||
sources: {
|
||||
'vector_layer_': {
|
||||
|
@ -62,37 +66,88 @@
|
|||
}
|
||||
},
|
||||
layers: []
|
||||
}
|
||||
});
|
||||
map.addControl(new maplibregl.NavigationControl());
|
||||
var inspect = new MaplibreInspect({
|
||||
showInspectMap: true,
|
||||
showInspectButton: false
|
||||
});
|
||||
map.addControl(inspect);
|
||||
map.on('styledata', function() {
|
||||
var layerList = document.getElementById('layerList');
|
||||
layerList.innerHTML = '';
|
||||
Object.keys(inspect.sources).forEach(function(sourceId) {
|
||||
var layerIds = inspect.sources[sourceId];
|
||||
layerIds.forEach(function(layerId) {
|
||||
var item = document.createElement('div');
|
||||
item.innerHTML = '<div style="' +
|
||||
'background:' + inspect.assignLayerColor(layerId) + ';' +
|
||||
'"></div> ' + layerId;
|
||||
layerList.appendChild(item);
|
||||
});
|
||||
})
|
||||
});
|
||||
};
|
||||
{{/is_terrain}}
|
||||
{{#is_terrain}}
|
||||
var style = {
|
||||
version: 8,
|
||||
sources: {
|
||||
"terrain": {
|
||||
"type": "raster-dem",
|
||||
"url": "{{public_url}}data/{{id}}.json",
|
||||
"encoding": "{{terrain_encoding}}"
|
||||
},
|
||||
"hillshade": {
|
||||
"type": "raster-dem",
|
||||
"url": "{{public_url}}data/{{id}}.json",
|
||||
"encoding": "{{terrain_encoding}}"
|
||||
}
|
||||
},
|
||||
"terrain": {
|
||||
"source": "terrain"
|
||||
},
|
||||
layers: [
|
||||
{
|
||||
"id": "background",
|
||||
"paint": {
|
||||
{{^if is_terrainrgb}}
|
||||
"background-color": "hsl(190, 99%, 63%)"
|
||||
{{else}}
|
||||
"background-color": "hsl(0, 100%, 25%)"
|
||||
{{/if}}
|
||||
},
|
||||
"type": "background"
|
||||
},
|
||||
{
|
||||
"id": "hillshade",
|
||||
"source": "hillshade",
|
||||
"type": "hillshade",
|
||||
"paint": {
|
||||
"hillshade-shadow-color": "hsl(39, 21%, 33%)",
|
||||
"hillshade-illumination-direction": 315,
|
||||
"hillshade-exaggeration": 0.8
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
{{/is_terrain}}
|
||||
|
||||
var map = new maplibregl.Map({
|
||||
container: 'map',
|
||||
hash: true,
|
||||
maxPitch: 85,
|
||||
style: style
|
||||
});
|
||||
map.addControl(new maplibregl.NavigationControl());
|
||||
{{^is_terrain}}
|
||||
var inspect = new MaplibreInspect({
|
||||
showInspectMap: true,
|
||||
showInspectButton: false
|
||||
});
|
||||
map.addControl(inspect);
|
||||
map.on('styledata', function() {
|
||||
var layerList = document.getElementById('layerList');
|
||||
layerList.innerHTML = '';
|
||||
Object.keys(inspect.sources).forEach(function(sourceId) {
|
||||
var layerIds = inspect.sources[sourceId];
|
||||
layerIds.forEach(function(layerId) {
|
||||
var item = document.createElement('div');
|
||||
item.innerHTML = '<div style="' +
|
||||
'background:' + inspect.assignLayerColor(layerId) + ';' +
|
||||
'"></div> ' + layerId;
|
||||
layerList.appendChild(item);
|
||||
});
|
||||
})
|
||||
});
|
||||
{{/is_terrain}}
|
||||
</script>
|
||||
{{/is_vector}}
|
||||
{{^is_vector}}
|
||||
{{/use_maplibre}}
|
||||
{{^use_maplibre}}
|
||||
<h1 style="display:none;">{{name}}</h1>
|
||||
<div id='map'></div>
|
||||
<script>
|
||||
var keyMatch = location.search.match(/[\?\&]key=([^&]+)/i);
|
||||
var keyParam = keyMatch ? '?key=' + keyMatch[1] : '';
|
||||
|
||||
var keyMatch = location.search.match(/[\?\&]key=([^&]+)/i);
|
||||
var keyParam = keyMatch ? '?key=' + keyMatch[1] : '';
|
||||
var map = L.map('map', { zoomControl: false });
|
||||
new L.Control.Zoom({ position: 'topright' }).addTo(map);
|
||||
|
||||
|
@ -141,6 +196,6 @@
|
|||
new L.Hash(map);
|
||||
}, 0);
|
||||
</script>
|
||||
{{/is_vector}}
|
||||
{{/use_maplibre}}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -6,10 +6,15 @@
|
|||
<title>TileServer GL - Server for vector and raster maps with GL styles</title>
|
||||
<link rel="stylesheet" type="text/css" href="{{public_url}}index.css{{&key_query}}" />
|
||||
<script>
|
||||
function toggle_xyz(id) {
|
||||
function toggle_link(id, link) {
|
||||
var el = document.getElementById(id);
|
||||
var s = el.style;
|
||||
s.display = s.display == 'none' ? 'inline-block' : 'none';
|
||||
if (s.display == 'none') {
|
||||
s.display = 'inline-block';
|
||||
} else if (el.value == link) {
|
||||
s.display = 'none';
|
||||
}
|
||||
el.value = link;
|
||||
el.setSelectionRange(0, el.value.length);
|
||||
return false;
|
||||
}
|
||||
|
@ -37,7 +42,7 @@
|
|||
<div class="filter-details">
|
||||
<h3>Filter styles and data by name or identifier</h3>
|
||||
<!-- filter input , needs to call filter() when content changes...-->
|
||||
<input id="filter" type="text" oninput="filter()" placeholder="Start typing name or identifier" />
|
||||
<input id="filter" type="text" oninput="filter()" placeholder="Start typing name or identifier" autofocus />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -66,8 +71,8 @@
|
|||
| <a href="{{public_url}}styles/{{@key}}/wmts.xml{{&../key_query}}">WMTS</a>
|
||||
{{/if}}
|
||||
{{#if xyz_link}}
|
||||
| <a href="#" onclick="return toggle_xyz('xyz_style_{{@key}}');">XYZ</a>
|
||||
<input id="xyz_style_{{@key}}" type="text" value="{{&xyz_link}}" style="display:none;" />
|
||||
| <a href="#" onclick="return toggle_link('xyz_style_{{@key}}', '{{&xyz_link}}');">XYZ</a>
|
||||
<input id="xyz_style_{{@key}}" type="text" value="" style="display:none;" />
|
||||
{{/if}}
|
||||
</p>
|
||||
</div>
|
||||
|
@ -105,9 +110,12 @@
|
|||
<p class="services">
|
||||
services: <a href="{{public_url}}data/{{@key}}.json{{&../key_query}}">TileJSON</a>
|
||||
{{#if xyz_link}}
|
||||
| <a href="#" onclick="return toggle_xyz('xyz_data_{{@key}}');">XYZ</a>
|
||||
<input id="xyz_data_{{@key}}" type="text" value="{{&xyz_link}}" style="display:none;" />
|
||||
| <a href="#" onclick="return toggle_link('link_data_{{@key}}', '{{&xyz_link}}');">XYZ</a>
|
||||
{{/if}}
|
||||
{{#if elevation_link}}
|
||||
| <a href="#" onclick="return toggle_link('link_data_{{@key}}', '{{&elevation_link}}');">Elevation</a>
|
||||
{{/if}}
|
||||
<input id="link_data_{{@key}}" type="text" value="" style="display:none;" />
|
||||
</p>
|
||||
</div>
|
||||
<div class="viewers">
|
||||
|
@ -116,6 +124,9 @@
|
|||
{{/is_vector}}
|
||||
{{^is_vector}}
|
||||
<a class="btn" href="{{public_url}}data/{{@key}}/{{&../key_query}}{{viewer_hash}}">View</a>
|
||||
{{#elevation_link}}
|
||||
<a class="btn" href="{{public_url}}data/preview/{{@key}}/{{&../key_query}}{{viewer_hash}}">Preview</a>
|
||||
{{/elevation_link}}
|
||||
{{/is_vector}}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -595,18 +595,22 @@ function start(opts) {
|
|||
};
|
||||
});
|
||||
|
||||
serveTemplate('/data/:id/$', 'data', (req) => {
|
||||
const { id } = req.params;
|
||||
serveTemplate('/data/(:preview(preview)/)?:id/', 'data', (req) => {
|
||||
const id = req.params.id;
|
||||
const preview = req.params.preview || undefined;
|
||||
const data = serving.data[id];
|
||||
|
||||
if (!data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const is_terrain = ((data.tileJSON.encoding === 'terrarium' || data.tileJSON.encoding === 'mapbox') && (preview === "preview"));
|
||||
return {
|
||||
...data,
|
||||
id,
|
||||
is_vector: data.tileJSON.format === 'pbf',
|
||||
use_maplibre: (data.tileJSON.format === 'pbf' || is_terrain),
|
||||
is_terrain: is_terrain,
|
||||
is_terrainrgb: (data.tileJSON.encoding === "mapbox"),
|
||||
terrain_encoding: data.tileJSON.encoding,
|
||||
};
|
||||
});
|
||||
|
||||
|
|
10
src/utils.js
10
src/utils.js
|
@ -119,16 +119,22 @@ export const getTileUrls = (
|
|||
tileParams = `${tileSize}/{z}/{x}/{y}`;
|
||||
}
|
||||
|
||||
if (format && format != "") {
|
||||
format = `.${format}`;
|
||||
} else {
|
||||
format = "";
|
||||
}
|
||||
|
||||
const uris = [];
|
||||
if (!publicUrl) {
|
||||
let xForwardedPath = `${req.get('X-Forwarded-Path') ? '/' + req.get('X-Forwarded-Path') : ''}`;
|
||||
for (const domain of domains) {
|
||||
uris.push(
|
||||
`${req.protocol}://${domain}${xForwardedPath}/${path}/${tileParams}.${format}${query}`,
|
||||
`${req.protocol}://${domain}${xForwardedPath}/${path}/${tileParams}${format}${query}`,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
uris.push(`${publicUrl}${path}/${tileParams}.${format}${query}`);
|
||||
uris.push(`${publicUrl}${path}/${tileParams}${format}${query}`);
|
||||
}
|
||||
|
||||
return uris;
|
||||
|
|
Loading…
Reference in a new issue