Compare commits

...

14 Commits
v0.4 ... v0.6

Author SHA1 Message Date
Petr Sloup
d6e2baef67 Update version to 0.6.0 2016-06-29 20:31:13 +02:00
Petr Sloup
6100013718 Fix serving the same style twice 2016-06-29 20:28:56 +02:00
Petr Sloup
4eea8a91b8 Add favicon.ico 2016-06-29 20:25:36 +02:00
Petr Sloup
d57f9f7a60 Fix and improve xray viewer 2016-06-29 20:23:37 +02:00
Petr Sloup
1307b29ff9 Cleaner implementation of keys 2016-06-29 20:17:58 +02:00
Petr Sloup
a9443edfc6 Update mapbox-gl-js to v0.19.0 2016-06-29 20:08:21 +02:00
Petr Sloup
e6a1bf407c Remove sourceMappingURL 2016-06-29 20:08:09 +02:00
Petr Sloup
0ba2dcce53 Always use http for wmts 2016-06-29 19:55:06 +02:00
Petr Sloup
ebd6662ebb Minor WMTS link bugfix 2016-06-29 16:23:49 +02:00
Petr Sloup
6898be5bea Update version 2016-06-29 16:12:42 +02:00
Petr Sloup
a55b5ad69c Fix viewer vector/raster autodetection 2016-06-29 15:14:51 +02:00
Petr Sloup
1104bf8a57 Add links to WMTS services from index.html 2016-06-29 15:08:56 +02:00
Petr Sloup
1d4503b507 If key present in query, propagate it to other linked urls 2016-06-29 14:57:11 +02:00
Petr Sloup
2d5dccc1e0 Update dependencies 2016-06-28 07:48:30 +02:00
11 changed files with 371 additions and 296 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "tileserver-gl", "name": "tileserver-gl",
"version": "0.0.3", "version": "0.6.0",
"description": "Map tile server for JSON GL styles - serverside generated raster tiles", "description": "Map tile server for JSON GL styles - serverside generated raster tiles",
"main": "src/main.js", "main": "src/main.js",
"authors": [ "authors": [
@@ -19,7 +19,7 @@
"advanced-pool": "0.3.2", "advanced-pool": "0.3.2",
"canvas": "1.4.0", "canvas": "1.4.0",
"clone": "1.0.2", "clone": "1.0.2",
"color": "0.11.2", "color": "0.11.3",
"cors": "2.7.1", "cors": "2.7.1",
"express": "4.14.0", "express": "4.14.0",
"handlebars": "4.0.5", "handlebars": "4.0.5",

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -78,6 +78,11 @@
padding: 5px; padding: 5px;
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0A%20%20%3Cpath%20style%3D%27fill%3A%23333333%3B%27%20d%3D%27M%2010%206%20C%209.446%206%209%206.4459904%209%207%20L%209%209%20L%207%209%20C%206.446%209%206%209.446%206%2010%20C%206%2010.554%206.446%2011%207%2011%20L%209%2011%20L%209%2013%20C%209%2013.55401%209.446%2014%2010%2014%20C%2010.554%2014%2011%2013.55401%2011%2013%20L%2011%2011%20L%2013%2011%20C%2013.554%2011%2014%2010.554%2014%2010%20C%2014%209.446%2013.554%209%2013%209%20L%2011%209%20L%2011%207%20C%2011%206.4459904%2010.554%206%2010%206%20z%27%20%2F%3E%0A%3C%2Fsvg%3E%0A"); background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0A%20%20%3Cpath%20style%3D%27fill%3A%23333333%3B%27%20d%3D%27M%2010%206%20C%209.446%206%209%206.4459904%209%207%20L%209%209%20L%207%209%20C%206.446%209%206%209.446%206%2010%20C%206%2010.554%206.446%2011%207%2011%20L%209%2011%20L%209%2013%20C%209%2013.55401%209.446%2014%2010%2014%20C%2010.554%2014%2011%2013.55401%2011%2013%20L%2011%2011%20L%2013%2011%20C%2013.554%2011%2014%2010.554%2014%2010%20C%2014%209.446%2013.554%209%2013%209%20L%2011%209%20L%2011%207%20C%2011%206.4459904%2010.554%206%2010%206%20z%27%20%2F%3E%0A%3C%2Fsvg%3E%0A");
} }
.mapboxgl-ctrl-icon.mapboxgl-ctrl-geolocate {
padding: 5px;
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%3Cpath%20style%3D%27fill%3A%23333333%3B%27%20d%3D%27M13%2C7%20L10.5%2C11.75%20L10.25%2C10%20z%20M13.888%2C6.112%20C13.615%2C5.84%2013.382%2C6.076%2012.5%2C6.5%20C10.14%2C7.634%206%2C10%206%2C10%20L9.5%2C10.5%20L10%2C14%20C10%2C14%2012.366%2C9.86%2013.5%2C7.5%20C13.924%2C6.617%2014.16%2C6.385%2013.888%2C6.112%27%2F%3E%3C%2Fsvg%3E");
}
.mapboxgl-ctrl-icon.mapboxgl-ctrl-compass > div.arrow { .mapboxgl-ctrl-icon.mapboxgl-ctrl-compass > div.arrow {
width: 20px; width: 20px;
height: 20px; height: 20px;
@@ -106,6 +111,8 @@
.mapboxgl-popup { .mapboxgl-popup {
position: absolute; position: absolute;
top: 0;
left: 0;
display: -webkit-flex; display: -webkit-flex;
display: flex; display: flex;
will-change: transform; will-change: transform;

File diff suppressed because one or more lines are too long

View File

@@ -65,5 +65,3 @@ module.exports=window.L=require("leaflet/dist/leaflet-src");
"use strict";function contains(n,t){if(!t||!t.length)return!1;for(var r=0;r<t.length;r++)if(t[r]===n)return!0;return!1}module.exports={idUrl:function(n,t){-1===n.indexOf("/")?t.loadID(n):t.loadURL(n)},log:function(n){"object"==typeof console&&"function"==typeof console.error&&console.error(n)},strict:function(n,t){if(typeof n!==t)throw new Error("Invalid argument: "+t+" expected")},strict_instance:function(n,t,r){if(!(n instanceof t))throw new Error("Invalid argument: "+r+" expected")},strict_oneof:function(n,t){if(!contains(n,t))throw new Error("Invalid argument: "+n+" given, valid values are "+t.join(", "))},strip_tags:function(n){return n.replace(/<[^<]+>/g,"")},lbounds:function(n){return new L.LatLngBounds([[n[1],n[0]],[n[3],n[2]]])}}; "use strict";function contains(n,t){if(!t||!t.length)return!1;for(var r=0;r<t.length;r++)if(t[r]===n)return!0;return!1}module.exports={idUrl:function(n,t){-1===n.indexOf("/")?t.loadID(n):t.loadURL(n)},log:function(n){"object"==typeof console&&"function"==typeof console.error&&console.error(n)},strict:function(n,t){if(typeof n!==t)throw new Error("Invalid argument: "+t+" expected")},strict_instance:function(n,t,r){if(!(n instanceof t))throw new Error("Invalid argument: "+r+" expected")},strict_oneof:function(n,t){if(!contains(n,t))throw new Error("Invalid argument: "+n+" given, valid values are "+t.join(", "))},strip_tags:function(n){return n.replace(/<[^<]+>/g,"")},lbounds:function(n){return new L.LatLngBounds([[n[1],n[0]],[n[3],n[2]]])}};
},{}]},{},[17]) },{}]},{},[17])
//# sourceMappingURL=mapbox.js.map

View File

@@ -4,8 +4,8 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>{{name}} - TileServer GL</title> <title>{{name}} - TileServer GL</title>
{{#is_vector}} {{#is_vector}}
<link rel="stylesheet" type="text/css" href="/mapbox-gl.css" /> <link rel="stylesheet" type="text/css" href="/mapbox-gl.css{{&key_query}}" />
<script src="/mapbox-gl.js"></script> <script src="/mapbox-gl.js{{&key_query}}"></script>
<style> <style>
body {background:#000;color:#ccc;} body {background:#000;color:#ccc;}
#map {position:absolute;top:0;left:0;right:250px;bottom:0;} #map {position:absolute;top:0;left:0;right:250px;bottom:0;}
@@ -16,9 +16,9 @@
</style> </style>
{{/is_vector}} {{/is_vector}}
{{^is_vector}} {{^is_vector}}
<link rel="stylesheet" type="text/css" href="/mapbox.css" /> <link rel="stylesheet" type="text/css" href="/mapbox.css{{&key_query}}" />
<script src="/mapbox.js"></script> <script src="/mapbox.js{{&key_query}}"></script>
<script src="/leaflet-hash.js"></script> <script src="/leaflet-hash.js{{&key_query}}"></script>
<style> <style>
body { margin:0; padding:0; } body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; } #map { position:absolute; top:0; bottom:0; width:100%; }
@@ -97,18 +97,24 @@
} }
}; };
xhttp.responseType = 'json'; xhttp.responseType = 'json';
xhttp.open('GET', '/data/{{id}}.json', true); xhttp.open('GET', '/data/{{id}}.json{{&key_query}}', true);
xhttp.send(); xhttp.send();
var propertyList = document.getElementById('propertyList'); var propertyList = document.getElementById('propertyList');
map.on('mousemove', function(e) { map.on('mousemove', function(e) {
propertyList.innerHTML = ''; propertyList.innerHTML = '';
map.featuresAt(e.point, {radius: 3}, function(err, features) { var width = 3, height = 3;
if (err) throw err; var features = map.queryRenderedFeatures([
if (features[0]) { [e.point.x - width / 2, e.point.y - height / 2],
propertyList.innerHTML = JSON.stringify(features[0].properties, null, 2); [e.point.x + width / 2, e.point.y + height / 2]
} ]);
if (features) {
var html = '';
features.forEach(function(feature) {
html += JSON.stringify(feature.properties, null, 2) + '\n';
}); });
propertyList.innerHTML = html;
}
}); });
</script> </script>
{{/is_vector}} {{/is_vector}}
@@ -116,7 +122,7 @@
<h1 style="display:none;">{{name}}</h1> <h1 style="display:none;">{{name}}</h1>
<div id='map'></div> <div id='map'></div>
<script> <script>
var map = L.mapbox.map('map', '/data/{{id}}.json', { zoomControl: false }); var map = L.mapbox.map('map', '/data/{{id}}.json{{&key_query}}', { zoomControl: false });
new L.Control.Zoom({ position: 'topright' }).addTo(map); new L.Control.Zoom({ position: 'topright' }).addTo(map);
setTimeout(function() { setTimeout(function() {
new L.Hash(map); new L.Hash(map);

View File

@@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>TileServerGL</title> <title>TileServerGL</title>
<link rel="stylesheet" type="text/css" href="/index.css" /> <link rel="stylesheet" type="text/css" href="/index.css{{&key_query}}" />
</head> </head>
<body> <body>
<section> <section>
@@ -13,25 +13,28 @@
{{#each styles}} {{#each styles}}
<div class="item"> <div class="item">
{{#if thumbnail}} {{#if thumbnail}}
<img src="/styles/{{@key}}/rendered/{{thumbnail}}" alt="{{name}} preview" /> <img src="/styles/{{@key}}/rendered/{{thumbnail}}{{&../key_query}}" alt="{{name}} preview" />
{{else}} {{else}}
<div class="sample-img"></div> <div class="sample-img"></div>
{{/if}} {{/if}}
<h3>{{name}}</h3> <h3>{{name}}</h3>
<p>Id: {{@key}} <p>Id: {{@key}}
{{#if serving_rendered}} {{#if serving_rendered}}
| <a href="/styles/{{@key}}/rendered.json">TileJSON</a> | <a href="/styles/{{@key}}/rendered.json{{&../key_query}}">TileJSON</a>
{{#if wmts_link}}
| <a href="{{&wmts_link}}">WMTS Service</a>
{{/if}}
{{/if}} {{/if}}
</p> </p>
{{#if serving_data}} {{#if serving_data}}
<a class="btn" href="/styles/{{@key}}/?vector{{viewer_hash}}">Vector view</a> <a class="btn" href="/styles/{{@key}}/?{{&../key_query_part}}vector{{viewer_hash}}">Vector view</a>
{{/if}} {{/if}}
{{#if serving_rendered}} {{#if serving_rendered}}
<a class="btn" href="/styles/{{@key}}/?raster{{viewer_hash}}">Raster view</a> <a class="btn" href="/styles/{{@key}}/?{{&../key_query_part}}raster{{viewer_hash}}">Raster view</a>
{{/if}} {{/if}}
{{#if serving_data}} {{#if serving_data}}
{{#if serving_rendered}} {{#if serving_rendered}}
<a class="btn" href="/styles/{{@key}}/{{viewer_hash}}">Auto view</a> <a class="btn" href="/styles/{{@key}}/{{&../key_query}}{{viewer_hash}}">Auto view</a>
{{/if}} {{/if}}
{{/if}} {{/if}}
</div> </div>
@@ -42,17 +45,22 @@
{{#each data}} {{#each data}}
<div class="item"> <div class="item">
{{#if thumbnail}} {{#if thumbnail}}
<img src="/data/{{@key}}/{{thumbnail}}" alt="{{name}} preview" /> <img src="/data/{{@key}}/{{thumbnail}}{{&../key_query}}" alt="{{name}} preview" />
{{else}} {{else}}
<div class="sample-img"></div> <div class="sample-img"></div>
{{/if}} {{/if}}
<h3>{{name}}</h3> <h3>{{name}}</h3>
<p>Id: {{@key}} |{{#if formatted_filesize}} {{formatted_filesize}} |{{/if}} {{#is_vector}}Vector{{/is_vector}}{{^is_vector}}Raster{{/is_vector}} data | <a href="/data/{{@key}}.json">TileJSON</a></p> <p>Id: {{@key}} |{{#if formatted_filesize}} {{formatted_filesize}} |{{/if}} {{#is_vector}}Vector{{/is_vector}}{{^is_vector}}Raster{{/is_vector}} data
| <a href="/data/{{@key}}.json{{&../key_query}}">TileJSON</a>
{{#if wmts_link}}
| <a href="{{&wmts_link}}">WMTS Service</a>
{{/if}}
</p>
{{#is_vector}} {{#is_vector}}
<a class="btn" href="/data/{{@key}}/{{viewer_hash}}">X-Ray view</a> <a class="btn" href="/data/{{@key}}/{{&../key_query}}{{viewer_hash}}">X-Ray view</a>
{{/is_vector}} {{/is_vector}}
{{^is_vector}} {{^is_vector}}
<a class="btn" href="/data/{{@key}}/{{viewer_hash}}">Raster view</a> <a class="btn" href="/data/{{@key}}/{{&../key_query}}{{viewer_hash}}">Raster view</a>
{{/is_vector}} {{/is_vector}}
</div> </div>
{{/each}} {{/each}}

View File

@@ -3,11 +3,11 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>{{name}} - TileServer GL</title> <title>{{name}} - TileServer GL</title>
<link rel="stylesheet" type="text/css" href="/mapbox-gl.css" /> <link rel="stylesheet" type="text/css" href="/mapbox-gl.css{{&key_query}}" />
<script src="/mapbox-gl.js"></script> <script src="/mapbox-gl.js{{&key_query}}"></script>
<link rel="stylesheet" type="text/css" href="/mapbox.css" /> <link rel="stylesheet" type="text/css" href="/mapbox.css{{&key_query}}" />
<script src="/mapbox.js"></script> <script src="/mapbox.js{{&key_query}}"></script>
<script src="/leaflet-hash.js"></script> <script src="/leaflet-hash.js{{&key_query}}"></script>
<style> <style>
body { margin:0; padding:0; } body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; } #map { position:absolute; top:0; bottom:0; width:100%; }
@@ -17,19 +17,20 @@
<h1 style="display:none;">{{name}}</h1> <h1 style="display:none;">{{name}}</h1>
<div id='map'></div> <div id='map'></div>
<script> <script>
var preference = (location.search || '').substr(1); var q = (location.search || '').substr(1).split('&');
if (preference != 'vector' && preference != 'raster') { var preference =
preference = mapboxgl.supported() ? 'vector' : 'raster'; q.indexOf('vector') >= 0 ? 'vector' :
} (q.indexOf('raster') >= 0 ? 'raster' :
(mapboxgl.supported() ? 'vector' : 'raster'));
if (preference == 'vector') { if (preference == 'vector') {
var map = new mapboxgl.Map({ var map = new mapboxgl.Map({
container: 'map', container: 'map',
style: '/styles/{{id}}.json', style: '/styles/{{id}}.json{{&key_query}}',
hash: true hash: true
}); });
map.addControl(new mapboxgl.Navigation()); map.addControl(new mapboxgl.Navigation());
} else { } else {
var map = L.mapbox.map('map', '/styles/{{id}}/rendered.json', { zoomControl: false }); var map = L.mapbox.map('map', '/styles/{{id}}/rendered.json{{&key_query}}', { zoomControl: false });
new L.Control.Zoom({ position: 'topright' }).addTo(map); new L.Control.Zoom({ position: 'topright' }).addTo(map);
setTimeout(function() { setTimeout(function() {
new L.Hash(map); new L.Hash(map);

View File

@@ -137,7 +137,7 @@ module.exports = function(options, repo, params, id) {
}); });
}; };
styleJSON = require(path.join(options.paths.styles, styleFile)); styleJSON = clone(require(path.join(options.paths.styles, styleFile)));
styleJSON.sprite = 'sprites://' + path.basename(styleFile, '.json'); styleJSON.sprite = 'sprites://' + path.basename(styleFile, '.json');
styleJSON.glyphs = 'fonts://{fontstack}/{range}.pbf'; styleJSON.glyphs = 'fonts://{fontstack}/{range}.pbf';

View File

@@ -46,9 +46,13 @@ module.exports = function(options, repo, params, id, reportTiles, reportFont) {
repo[id] = styleJSON; repo[id] = styleJSON;
app.get('/' + id + '.json', function(req, res, next) { app.get('/' + id + '.json', function(req, res, next) {
var fixUrl = function(url) { var fixUrl = function(url, opt_nokey) {
var query = '';
if (!opt_nokey && req.query.key) {
query = '?key=' + req.query.key;
}
return url.replace( return url.replace(
'local://', req.protocol + '://' + req.headers.host + '/'); 'local://', req.protocol + '://' + req.headers.host + '/') + query;
}; };
var styleJSON_ = clone(styleJSON); var styleJSON_ = clone(styleJSON);
@@ -56,7 +60,8 @@ module.exports = function(options, repo, params, id, reportTiles, reportFont) {
var source = styleJSON_.sources[name]; var source = styleJSON_.sources[name];
source.url = fixUrl(source.url); source.url = fixUrl(source.url);
}); });
styleJSON_.sprite = fixUrl(styleJSON_.sprite); // mapbox-gl-js viewer cannot handle sprite urls with query
styleJSON_.sprite = fixUrl(styleJSON_.sprite, true);
styleJSON_.glyphs = fixUrl(styleJSON_.glyphs); styleJSON_.glyphs = fixUrl(styleJSON_.glyphs);
return res.send(styleJSON_); return res.send(styleJSON_);
}); });

View File

@@ -45,7 +45,7 @@ module.exports = function(opts, callback) {
var config; var config;
try { try {
config = require(configPath); config = clone(require(configPath));
} catch (e) { } catch (e) {
console.log('ERROR: Config file not found or invalid!'); console.log('ERROR: Config file not found or invalid!');
console.log(' See README.md for instructions and sample data.'); console.log(' See README.md for instructions and sample data.');
@@ -118,13 +118,15 @@ module.exports = function(opts, callback) {
app.get('/styles.json', function(req, res, next) { app.get('/styles.json', function(req, res, next) {
var result = []; var result = [];
var query = req.query.key ? ('?key=' + req.query.key) : '';
Object.keys(serving.styles).forEach(function(id) { Object.keys(serving.styles).forEach(function(id) {
var styleJSON = serving.styles[id]; var styleJSON = serving.styles[id];
result.push({ result.push({
version: styleJSON.version, version: styleJSON.version,
name: styleJSON.name, name: styleJSON.name,
id: id, id: id,
url: req.protocol + '://' + req.headers.host + '/styles/' + id + '.json' url: req.protocol + '://' + req.headers.host +
'/styles/' + id + '.json' + query
}); });
}); });
res.send(result); res.send(result);
@@ -165,17 +167,20 @@ module.exports = function(opts, callback) {
app.use(path, function(req, res, next) { app.use(path, function(req, res, next) {
var data = {}; var data = {};
if (dataGetter) { if (dataGetter) {
data = dataGetter(req.params); data = dataGetter(req);
if (!data) { if (!data) {
return res.status(404).send('Not found'); return res.status(404).send('Not found');
} }
} }
data['key_query_part'] =
req.query.key ? 'key=' + req.query.key + '&amp;' : '';
data['key_query'] = req.query.key ? '?key=' + req.query.key : '';
return res.status(200).send(compiled(data)); return res.status(200).send(compiled(data));
}); });
}); });
}; };
serveTemplate('/$', 'index', function() { serveTemplate('/$', 'index', function(req) {
var styles = clone(config.styles || {}); var styles = clone(config.styles || {});
Object.keys(styles).forEach(function(id) { Object.keys(styles).forEach(function(id) {
var style = styles[id]; var style = styles[id];
@@ -194,6 +199,12 @@ module.exports = function(opts, callback) {
Math.floor(centerPx[0] / 256) + '/' + Math.floor(centerPx[0] / 256) + '/' +
Math.floor(centerPx[1] / 256) + '.png'; Math.floor(centerPx[1] / 256) + '.png';
} }
var query = req.query.key ? ('?key=' + req.query.key) : '';
style.wmts_link = 'https://wmts.maptiler.com/' +
new Buffer(req.protocol + '://' + req.headers.host +
'/styles/' + id + '/rendered.json' + query).toString('base64') +
'/wmts';
} }
}); });
var data = clone(serving.data || {}); var data = clone(serving.data || {});
@@ -213,6 +224,11 @@ module.exports = function(opts, callback) {
Math.floor(centerPx[0] / 256) + '/' + Math.floor(centerPx[0] / 256) + '/' +
Math.floor(centerPx[1] / 256) + '.' + data_.format; Math.floor(centerPx[1] / 256) + '.' + data_.format;
} }
var query = req.query.key ? ('?key=' + req.query.key) : '';
data_.wmts_link = 'http://wmts.maptiler.com/' +
new Buffer('http://' + req.headers.host +
'/data/' + id + '.json' + query).toString('base64') + '/wmts';
} }
if (data_.filesize) { if (data_.filesize) {
var suffix = 'kB'; var suffix = 'kB';
@@ -234,8 +250,8 @@ module.exports = function(opts, callback) {
}; };
}); });
serveTemplate('/styles/:id/$', 'viewer', function(params) { serveTemplate('/styles/:id/$', 'viewer', function(req) {
var id = params.id; var id = req.params.id;
var style = clone((config.styles || {})[id]); var style = clone((config.styles || {})[id]);
if (!style) { if (!style) {
return null; return null;
@@ -253,8 +269,8 @@ module.exports = function(opts, callback) {
}); });
*/ */
serveTemplate('/data/:id/$', 'data', function(params) { serveTemplate('/data/:id/$', 'data', function(req) {
var id = params.id; var id = req.params.id;
var data = clone(serving.data[id]); var data = clone(serving.data[id]);
if (!data) { if (!data) {
return null; return null;