Compare commits

...

23 Commits

Author SHA1 Message Date
Petr Sloup
c162a6647d Update package version to 1.3.0-beta.3 2017-01-12 15:26:34 +01:00
Petr Sloup
b48f7edc1d Serve fontstacks.json and possibly fonts even without any style 2017-01-12 15:23:02 +01:00
Petr Sloup
6d68c93871 Fix broken requires 2017-01-12 14:05:02 +01:00
Petr Sloup
1fef895e67 Update native dependency info in documentation 2017-01-12 13:57:40 +01:00
Petr Sloup
920b6c19b6 Remove deprecated engineStrict 2017-01-12 13:54:44 +01:00
Petr Sloup
7f280feeb1 Minor dependency package name update 2017-01-12 13:48:05 +01:00
Petr Sloup
1aec8f386e Update package version to 1.3.0-beta.2 2017-01-10 16:19:58 +01:00
Petr Sloup
d05606de4d Improved font serving 2017-01-10 16:17:51 +01:00
Petr Sloup
b9930dd195 Fix interim empty tile generation for raster layers 2017-01-10 15:47:56 +01:00
Petr Sloup
4082828790 Rename button from "X-Ray" to "Inspect" (see #103) 2017-01-10 15:17:34 +01:00
Petr Sloup
473e7b6f4a Merge pull request #103 from lukasmartinelli/master
Use Mapbox GL Inspect for X-Ray View
2017-01-10 15:15:06 +01:00
Lukas Martinelli
3d993458b5 Add different inspect viewer for data 2017-01-09 14:30:20 +01:00
Lukas Martinelli
b2dcf97d9a Add Mapbox GL Inspect plugin 2017-01-09 14:28:49 +01:00
Lukas Martinelli
d4ddbec45d Upgrade to Mapbox GL v0.30 2017-01-09 14:28:42 +01:00
Petr Sloup
d32e46ba2f Allow options to be passed to the docker + document it (close #87) 2016-12-21 07:01:16 +01:00
Petr Sloup
0ec992eb21 Explicitly handle SIGINT to terminate on Ctrl+C from docker
See https://github.com/nodejs/node/issues/4182
2016-12-21 06:49:16 +01:00
Petr Sloup
7a55ac9ebb Add paragraph about native dependencies (close #90) 2016-12-20 14:53:27 +01:00
Petr Sloup
78fcb893f7 Add paragraph about running behind a proxy (#50, #85) 2016-12-20 14:41:22 +01:00
Petr Sloup
19dcd52cc8 Update documentation to reflect recent changes 2016-12-20 14:32:33 +01:00
Petr Sloup
557f83121c Fix URLs in /index.json and /rendered.json 2016-12-20 13:56:23 +01:00
Petr Sloup
2d29a21596 Do not add basename to tilejson and remove sensitive properties (see #69) 2016-12-20 13:55:36 +01:00
Petr Sloup
945e568b2b Merge pull request #93 from ArsenyN/bugfix-RemoteVectorSource
Fix: Right code for working with external vector tiles.
2016-12-20 13:21:44 +01:00
Arseny Novikov
37db733e02 Fix for this comment: https://github.com/klokantech/tileserver-gl/issues/91#issuecomment-267939138
With this commit code will have right behaviour with external vector tiles.
2016-12-19 14:13:03 +03:00
20 changed files with 483 additions and 397 deletions

View File

@@ -27,4 +27,4 @@ VOLUME /data
WORKDIR /data
EXPOSE 80
CMD ["/usr/src/app/run.sh"]
ENTRYPOINT ["/usr/src/app/run.sh"]

View File

@@ -9,4 +9,4 @@ VOLUME /data
WORKDIR /data
EXPOSE 80
CMD ["node", "/usr/src/app/", "-p", "80"]
ENTRYPOINT ["node", "/usr/src/app/", "-p", "80"]

View File

@@ -10,7 +10,7 @@ Example::
"options": {
"paths": {
"root": "",
"fonts": "glyphs",
"fonts": "fonts",
"sprites": "sprites",
"styles": "styles",
"mbtiles": ""
@@ -25,7 +25,8 @@ Example::
"pngQuantization": false,
"png": 90
},
"maxSize": 2048
"maxSize": 2048,
"serveAllFonts": false
},
"styles": {
"basic": {
@@ -99,11 +100,14 @@ Each item specifies one data source which should be made accessible by the serve
The mbtiles file does not need to be specified here unless you explicitly want to serve the raw data.
Referencing local mbtiles from style
====================================
Referencing local files from style JSON
=======================================
You can link various data sources from the style JSON (for example even remote TileJSONs).
MBTiles
-------
To specify that you want to use local mbtiles, use to following syntax: ``mbtiles://switzerland.mbtiles``.
The TileServer-GL will try to find the file ``switzerland.mbtiles`` in ``root`` + ``mbtiles`` path.
@@ -119,3 +123,32 @@ For example::
Alternatively, you can use ``mbtiles://{zurich-vector}`` to reference existing data object from the config.
In this case, the server will look into the ``config.json`` to determine what mbtiles file to use.
For the config above, this is equivalent to ``mbtiles://zurich.mbtiles``.
Sprites
-------
If your style requires any sprites, make sure the style JSON contains proper path in the ``sprite`` property.
It can be a local path (e.g. ``my-style/sprite``) or remove http(s) location (e.g. ``https://mycdn.com/my-style/sprite``). Several possible extension are added to this path, so the following files should be present:
* ``sprite.json``
* ``sprite.png``
* ``sprite@2x.json``
* ``sprite@2x.png``
You can also use the following placeholders in the sprite path for easier use:
* ``{style}`` -- gets replaced with the name of the style file (``xxx.json``)
* ``{styleJsonFolder}`` -- gets replaced with the path to the style file
Fonts (glyphs)
--------------
Similarly to the sprites, the style JSON also needs to contain proper paths to the font glyphs (in the ``glyphs`` property) and can be both local and remote.
It should contain the following placeholders:
* ``{fontstack}`` -- name of the font and variant
* ``{range}`` -- range of the glyphs
For example ``"glyphs": "{fontstack}/{range}.pbf"`` will instruct TileServer-GL to look for the files such as ``fonts/Open Sans/0-255.pbf`` (``fonts`` come from the ``paths`` property of the ``config.json`` example above).

View File

@@ -13,3 +13,8 @@ Securing
========
Nginx can be used to add protection via https, password, referrer, IP address restriction, access keys, etc.
Running behind a proxy or a load-balancer
=========================================
If you need to run TileServer GL behind a proxy, make sure the proxy sends ``X-Forwarded-*`` headers to the server (most importantly ``X-Forwarded-Host`` and ``X-Forwaded-Proto``) to ensures the URLs generated inside TileJSON etc. are using the desired domain and protocol.

View File

@@ -43,6 +43,8 @@ Static images
* value of ``0.1`` means "add 10% size to each side to make sure the area of interest is nicely visible"
* You can also use (experimental) ``/styles/{id}/static/raw/...`` endpoints with raw spherical mercator coordinates (EPSG:3857) instead of WGS84.
* The static images are not available in the ``tileserver-gl-light`` version.
Source data
@@ -58,3 +60,7 @@ Source data
TileJSON arrays
===============
Array of all TileJSONs is at ``/index.json`` (``/rendered.json``; ``/data.json``)
List of available fonts
=======================
Array of names of the available fonts is at ``/fontstacks.json``

View File

@@ -9,11 +9,29 @@ When running docker image, no special installation is needed -- the docker will
Just run ``docker run -it -v $(pwd):/data -p 8080:80 klokantech/tileserver-gl``.
Additional options (see :doc:`/usage`) can be passed to the TileServer GL by appending them to the end of this command. You can, for example, do the following:
* ``docker run ... klokantech/tileserver-gl my-tiles.mbtiles`` -- explicitly specify which mbtiles to use (if you have more in the folder)
* ``docker run ... klokantech/tileserver-gl --verbose`` -- to see the default config created automatically
npm
===
Just run ``npm install -g tileserver-gl``.
Native dependencies
-------------------
There are some native dependencies that you need to make sure are installed if you plan to run the TileServer GL natively without docker.
The precise package names you need to install may differ on various platforms.
These are required on Debian 9:
* ``build-essential``
* ``libcairo2-dev``
* ``libprotobuf-dev``
``tileserver-gl-light`` on npm
==============================
@@ -23,7 +41,7 @@ Alternatively, you can use ``tileserver-gl-light`` package instead, which is pur
From source
===========
Make sure you have Node v4 or higher (nvm install 4) and run::
Make sure you have Node v4 (nvm install 4) and run::
npm install
node .
@@ -32,6 +50,9 @@ Make sure you have Node v4 or higher (nvm install 4) and run::
On OSX
======
Make sure to have ``pkg-config`` and ``cairo`` installed::
Make sure to have dependencies of canvas_ package installed::
brew install pkg-config cairo
brew install pkg-config cairo libpng jpeg giflib
.. _canvas: https://www.npmjs.com/package/canvas

View File

@@ -1,6 +1,6 @@
{
"name": "tileserver-gl",
"version": "1.3.0-beta.1",
"version": "1.3.0-beta.3",
"description": "Map tile server for JSON GL styles - vector and server side generated raster tiles",
"main": "src/main.js",
"bin": "src/main.js",
@@ -15,7 +15,6 @@
"engines": {
"node": ">=4.2.1 <5"
},
"engineStrict": true,
"scripts": {
"test": "mocha test/**.js"
},
@@ -25,7 +24,7 @@
"base64url": "2.0.0",
"canvas": "1.6.2",
"clone": "2.1.0",
"color": "1.0.2",
"color": "1.0.3",
"cors": "2.8.1",
"express": "4.14.0",
"glyph-pbf-composite": "0.0.2",
@@ -38,9 +37,9 @@
"pbf": "3.0.5",
"request": "2.79.0",
"sharp": "0.16.2",
"sphericalmercator": "1.0.5",
"tileserver-gl-styles": "1.0.0",
"vector-tile": "1.3.0"
"vector-tile": "1.3.0",
"@mapbox/sphericalmercator": "1.0.5"
},
"optionalDependencies": {
"tileshrink-gl": "./plugins/tileshrink-gl"

View File

@@ -0,0 +1,40 @@
.mapbox-gl-inspect_popup {
color: #333;
display: table;
}
.mapbox-gl-inspect_feature:not(:last-child) {
border-bottom: 1px solid #ccc;
}
.mapbox-gl-inspect_layer:before {
content: '#';
}
.mapbox-gl-inspect_layer {
display: block;
font-weight: bold;
}
.mapbox-gl-inspect_property {
display: table-row;
}
.mapbox-gl-inspect_property-value {
display: table-cell;
}
.mapbox-gl-inspect_property-name {
display: table-cell;
padding-right: 10px;
}
.mapboxgl-ctrl-inspect {
background-image: url('data:image/svg+xml;charset=utf8,<svg%20xmlns="http://www.w3.org/2000/svg"%20fill="#333333%22%20preserveAspectRatio=%22xMidYMid%20meet%22%20viewBox=%22-10%20-10%2060%2060%22%3E%3Cg%3E%3Cpath%20d=%22m15%2021.6q0-2%201.5-3.5t3.5-1.5%203.5%201.5%201.5%203.5-1.5%203.6-3.5%201.4-3.5-1.4-1.5-3.6z%20m18.4%2011.1l-6.4-6.5q1.4-2.1%201.4-4.6%200-3.4-2.5-5.8t-5.9-2.4-5.9%202.4-2.5%205.8%202.5%205.9%205.9%202.5q2.4%200%204.6-1.4l7.4%207.4q-0.9%200.6-2%200.6h-20q-1.3%200-2.3-0.9t-1.1-2.3l0.1-26.8q0-1.3%201-2.3t2.3-0.9h13.4l10%2010v19.3z%22%3E%3C/path%3E%3C/g%3E%3C/svg%3E');
}
.mapboxgl-ctrl-map {
background-image: url('data:image/svg+xml;charset=utf8,<svg%20xmlns="http://www.w3.org/2000/svg"%20fill="#333333%22%20viewBox=%22-10%20-10%2060%2060%22%20preserveAspectRatio=%22xMidYMid%20meet%22%3E%3Cg%3E%3Cpath%20d=%22m25%2031.640000000000004v-19.766666666666673l-10-3.511666666666663v19.766666666666666z%20m9.140000000000008-26.640000000000004q0.8599999999999923%200%200.8599999999999923%200.8600000000000003v25.156666666666666q0%200.625-0.625%200.783333333333335l-9.375%203.1999999999999993-10-3.5133333333333354-8.906666666666668%203.4383333333333326-0.2333333333333334%200.07833333333333314q-0.8616666666666664%200-0.8616666666666664-0.8599999999999994v-25.156666666666663q0-0.625%200.6233333333333331-0.7833333333333332l9.378333333333334-3.198333333333334%2010%203.5133333333333336%208.905000000000001-3.4383333333333344z%22%3E%3C/path%3E%3C/g%3E%3C/svg%3E');
}

File diff suppressed because one or more lines are too long

View File

@@ -70,17 +70,20 @@
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.mapboxgl-ctrl-icon.mapboxgl-ctrl-zoom-out {
.mapboxgl-ctrl-icon {
padding: 5px;
}
.mapboxgl-ctrl-icon.mapboxgl-ctrl-zoom-out {
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%207%2C9%20c%20-0.554%2C0%20-1%2C0.446%20-1%2C1%200%2C0.554%200.446%2C1%201%2C1%20l%206%2C0%20c%200.554%2C0%201%2C-0.446%201%2C-1%200%2C-0.554%20-0.446%2C-1%20-1%2C-1%20z%27%20%2F%3E%0A%3C%2Fsvg%3E%0A");
}
.mapboxgl-ctrl-icon.mapboxgl-ctrl-zoom-in {
padding: 5px;
.mapboxgl-ctrl-icon.mapboxgl-ctrl-zoom-in {
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;base64,PHN2ZyB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAyMCIgdmVyc2lvbj0iMS4xIj48cGF0aCBkPSJNMTAgNEM5IDQgOSA1IDkgNUw5IDUuMUE1IDUgMCAwIDAgNS4xIDlMNSA5QzUgOSA0IDkgNCAxMCA0IDExIDUgMTEgNSAxMUw1LjEgMTFBNSA1IDAgMCAwIDkgMTQuOUw5IDE1QzkgMTUgOSAxNiAxMCAxNiAxMSAxNiAxMSAxNSAxMSAxNUwxMSAxNC45QTUgNSAwIDAgMCAxNC45IDExTDE1IDExQzE1IDExIDE2IDExIDE2IDEwIDE2IDkgMTUgOSAxNSA5TDE0LjkgOUE1IDUgMCAwIDAgMTEgNS4xTDExIDVDMTEgNSAxMSA0IDEwIDR6TTEwIDYuNUEzLjUgMy41IDAgMCAxIDEzLjUgMTAgMy41IDMuNSAwIDAgMSAxMCAxMy41IDMuNSAzLjUgMCAwIDEgNi41IDEwIDMuNSAzLjUgMCAwIDEgMTAgNi41ek0xMCA4LjNBMS44IDEuOCAwIDAgMCA4LjMgMTAgMS44IDEuOCAwIDAgMCAxMCAxMS44IDEuOCAxLjggMCAwIDAgMTEuOCAxMCAxLjggMS44IDAgMCAwIDEwIDguM3oiIGZpbGw9IiMzMzMiLz48L3N2Zz4=");
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0D%0A%20%20%3Cpath%20style%3D%27fill%3A%23333%3B%27%20d%3D%27M10%204C9%204%209%205%209%205L9%205.1A5%205%200%200%200%205.1%209L5%209C5%209%204%209%204%2010%204%2011%205%2011%205%2011L5.1%2011A5%205%200%200%200%209%2014.9L9%2015C9%2015%209%2016%2010%2016%2011%2016%2011%2015%2011%2015L11%2014.9A5%205%200%200%200%2014.9%2011L15%2011C15%2011%2016%2011%2016%2010%2016%209%2015%209%2015%209L14.9%209A5%205%200%200%200%2011%205.1L11%205C11%205%2011%204%2010%204zM10%206.5A3.5%203.5%200%200%201%2013.5%2010%203.5%203.5%200%200%201%2010%2013.5%203.5%203.5%200%200%201%206.5%2010%203.5%203.5%200%200%201%2010%206.5zM10%208.3A1.8%201.8%200%200%200%208.3%2010%201.8%201.8%200%200%200%2010%2011.8%201.8%201.8%200%200%200%2011.8%2010%201.8%201.8%200%200%200%2010%208.3z%27%20%2F%3E%0D%0A%3C%2Fsvg%3E");
}
.mapboxgl-ctrl-icon.mapboxgl-ctrl-geolocate.watching {
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0D%0A%20%20%3Cpath%20style%3D%27fill%3A%2300f%3B%27%20d%3D%27M10%204C9%204%209%205%209%205L9%205.1A5%205%200%200%200%205.1%209L5%209C5%209%204%209%204%2010%204%2011%205%2011%205%2011L5.1%2011A5%205%200%200%200%209%2014.9L9%2015C9%2015%209%2016%2010%2016%2011%2016%2011%2015%2011%2015L11%2014.9A5%205%200%200%200%2014.9%2011L15%2011C15%2011%2016%2011%2016%2010%2016%209%2015%209%2015%209L14.9%209A5%205%200%200%200%2011%205.1L11%205C11%205%2011%204%2010%204zM10%206.5A3.5%203.5%200%200%201%2013.5%2010%203.5%203.5%200%200%201%2010%2013.5%203.5%203.5%200%200%201%206.5%2010%203.5%203.5%200%200%201%2010%206.5zM10%208.3A1.8%201.8%200%200%200%208.3%2010%201.8%201.8%200%200%200%2010%2011.8%201.8%201.8%200%200%200%2011.8%2010%201.8%201.8%200%200%200%2010%208.3z%27%20%2F%3E%0D%0A%3C%2Fsvg%3E");
}
.mapboxgl-ctrl-icon.mapboxgl-ctrl-compass > span.arrow {
@@ -94,9 +97,36 @@
.mapboxgl-ctrl.mapboxgl-ctrl-attrib {
padding: 0 5px;
background-color: rgba(255,255,255,0.5);
background-color: rgba(255, 255, 255, .5);
margin: 0;
}
.mapboxgl-ctrl-attrib.compact {
padding-top: 2px;
padding-bottom: 2px;
margin: 0 10px 10px 10px;
position: relative;
padding-right: 24px;
background-color: #fff;
border-radius: 3px 12px 12px 3px;
visibility: hidden;
}
.mapboxgl-ctrl-attrib.compact:hover {
visibility: visible;
}
.mapboxgl-ctrl-attrib.compact:after {
content: '';
cursor: pointer;
position: absolute;
bottom: 0;
right: 0;
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0D%0A%09%3Cpath%20fill%3D%27%23333333%27%20fill-rule%3D%27evenodd%27%20d%3D%27M4%2C10a6%2C6%200%201%2C0%2012%2C0a6%2C6%200%201%2C0%20-12%2C0%20M9%2C7a1%2C1%200%201%2C0%202%2C0a1%2C1%200%201%2C0%20-2%2C0%20M9%2C10a1%2C1%200%201%2C1%202%2C0l0%2C3a1%2C1%200%201%2C1%20-2%2C0%27%20%2F%3E%0D%0A%3C%2Fsvg%3E");
background-color: rgba(255, 255, 255, .5);
width: 24px;
height: 24px;
box-sizing: border-box;
visibility: visible;
border-radius: 12px;
}
.mapboxgl-ctrl-attrib a {
color: rgba(0,0,0,0.75);
text-decoration: none;

File diff suppressed because one or more lines are too long

View File

@@ -6,14 +6,15 @@
<title>{{name}} - TileServer GL</title>
{{#is_vector}}
<link rel="stylesheet" type="text/css" href="/mapbox-gl.css{{&key_query}}" />
<link rel="stylesheet" type="text/css" href="/mapbox-gl-inspect.css{{&key_query}}" />
<script src="/mapbox-gl.js{{&key_query}}"></script>
<script src="/mapbox-gl-inspect.min.js{{&key_query}}"></script>
<style>
body {background:#000;color:#ccc;}
body {background:#fff;color:#333;}
#map {position:absolute;top:0;left:0;right:250px;bottom:0;}
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:60%;width:240px;overflow:auto;}
#layerList div div {width:15px;height:15px;display:inline-block;}
#propertyList {position:absolute;top:40%;bottom:0;right:0;width:240px;overflow:auto;color:#fff;}
</style>
{{/is_vector}}
{{^is_vector}}
@@ -35,99 +36,37 @@
<script>
var map = new mapboxgl.Map({
container: 'map',
hash: true
});
map.addControl(new mapboxgl.NavigationControl());
function generateColor(str) {
var rgb = [0, 0, 0];
for (var i = 0; i < str.length; i++) {
var v = str.charCodeAt(i);
rgb[v % 3] = (rgb[i % 3] + (13*(v%13))) % 12;
}
var r = 4 + rgb[0];
var g = 4 + rgb[1];
var b = 4 + rgb[2];
r = (r * 16) + r;
g = (g * 16) + g;
b = (b * 16) + b;
return [r, g, b, 1];
};
function initLayer(data) {
var layer;
var layerList = document.getElementById('layerList');
var layers_ = [];
data['vector_layers'].forEach(function(el) {
var color = generateColor(el['id']);
var colorText = 'rgba(' + color[0] + ',' + color[1] + ',' + color[2] + ',' + color[3] + ')';
layers_.push({
id: el['id'] + Math.random(),
source: 'vector_layer_',
'source-layer': el['id'],
interactive: true,
type: 'line',
paint: {'line-color': colorText}
});
layers_.push({
id: el['id'] + Math.random(),
source: 'vector_layer_',
'source-layer': el['id'],
interactive: true,
type: 'circle',
paint: {'circle-color': colorText,
'circle-radius': 3},
filter: ["==", "$type", "Point"]
});
var item = document.createElement('div');
item.innerHTML = '<div style="' +
'background:rgba(' + color[0] + ',' + color[1] + ',' + color[2] + ',1);' +
'"></div> ' + el['id'];
layerList.appendChild(item);
});
map.setStyle({
hash: true,
style: {
version: 8,
sources: {
'vector_layer_': {
type: 'vector',
tiles: data['tiles'],
minzoom: data['minzoom'],
maxzoom: data['maxzoom']
url: '/data/{{id}}.json{{&key_query}}'
}
},
layers: layers_
});
return layer;
}
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
initLayer(xhttp.response);
layers: []
}
};
xhttp.responseType = 'json';
xhttp.open('GET', '/data/{{id}}.json{{&key_query}}', true);
xhttp.send();
var propertyList = document.getElementById('propertyList');
map.on('mousemove', function(e) {
propertyList.innerHTML = '';
var width = 3, height = 3;
var features = map.queryRenderedFeatures([
[e.point.x - width / 2, e.point.y - height / 2],
[e.point.x + width / 2, e.point.y + height / 2]
]);
if (features) {
var html = '';
features.forEach(function(feature) {
html +=
'[Layer: ' + feature.layer['source-layer'] + ']\n' +
JSON.stringify(feature.properties, null, 2) + '\n\n';
});
map.addControl(new mapboxgl.NavigationControl());
var inspect = new MapboxInspect({
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);
});
propertyList.innerHTML = html;
}
})
});
</script>
{{/is_vector}}

View File

@@ -89,10 +89,10 @@
</div>
<div class="viewers">
{{#is_vector}}
<a class="btn" href="/data/{{@key}}/{{&../key_query}}{{viewer_hash}}">X-Ray view</a>
<a class="btn" href="/data/{{@key}}/{{&../key_query}}{{viewer_hash}}">Inspect</a>
{{/is_vector}}
{{^is_vector}}
<a class="btn" href="/data/{{@key}}/{{&../key_query}}{{viewer_hash}}">Raster view</a>
<a class="btn" href="/data/{{@key}}/{{&../key_query}}{{viewer_hash}}">View</a>
{{/is_vector}}
</div>
</div>

2
run.sh
View File

@@ -1,3 +1,3 @@
#!/bin/bash
cd /data
xvfb-run -a -e /dev/stdout --server-args="-screen 0 1024x768x24" node /usr/src/app/ -p 80
xvfb-run -a -e /dev/stdout --server-args="-screen 0 1024x768x24" node /usr/src/app/ -p 80 "$@"

View File

@@ -41,8 +41,8 @@ module.exports = function(options, repo, params, id, styles) {
Object.assign(tileJSON, info);
tileJSON['tilejson'] = '2.0.0';
tileJSON['basename'] = id;
tileJSON['filesize'] = mbtilesFileStats['size'];
delete tileJSON['filesize'];
delete tileJSON['mtime'];
delete tileJSON['scheme'];
Object.assign(tileJSON, params.tilejson || {});

View File

@@ -19,7 +19,8 @@ module.exports = function(options, allowedFonts) {
files.forEach(function(file) {
fs.stat(path.join(fontPath, file), function(err, stats) {
if (!err) {
if (stats.isDirectory()) {
if (stats.isDirectory() &&
fs.existsSync(path.join(fontPath, file, '0-255.pbf'))) {
existingFonts[path.basename(file)] = true;
}
}
@@ -27,12 +28,13 @@ module.exports = function(options, allowedFonts) {
});
});
app.get('/:fontstack/:range([\\d]+-[\\d]+).pbf',
app.get('/fonts/:fontstack/:range([\\d]+-[\\d]+).pbf',
function(req, res, next) {
var fontstack = decodeURI(req.params.fontstack);
var range = req.params.range;
return utils.getFontsPbf(allowedFonts, fontPath, fontstack, range, existingFonts,
return utils.getFontsPbf(options.serveAllFonts ? null : allowedFonts,
fontPath, fontstack, range, existingFonts,
function(err, concated) {
if (err || concated.length === 0) {
console.log(err);
@@ -46,5 +48,12 @@ module.exports = function(options, allowedFonts) {
});
});
app.get('/fontstacks.json', function(req, res, next) {
res.header('Content-type', 'application/json');
return res.send(
Object.keys(options.serveAllFonts ? existingFonts : allowedFonts).sort()
);
});
return app;
};

View File

@@ -15,7 +15,7 @@ var Canvas = require('canvas'),
clone = require('clone'),
Color = require('color'),
express = require('express'),
mercator = new (require('sphericalmercator'))(),
mercator = new (require('@mapbox/sphericalmercator'))(),
mbgl = require('mapbox-gl-native'),
mbtiles = require('mbtiles'),
pngquant = require('node-pngquant-native'),
@@ -175,7 +175,6 @@ module.exports = function(options, repo, params, id, dataResolver) {
'tilejson': '2.0.0',
'name': styleJSON.name,
'attribution': '',
'basename': id,
'minzoom': 0,
'maxzoom': 20,
'bounds': [-180, -85.0511, 180, 85.0511],
@@ -192,7 +191,7 @@ module.exports = function(options, repo, params, id, dataResolver) {
var source = styleJSON.sources[name];
var url = source.url;
if (url.lastIndexOf('mbtiles:', 0) === 0) {
if (url && url.lastIndexOf('mbtiles:', 0) === 0) {
// found mbtiles source, replace with info from local file
delete source.url;
@@ -223,7 +222,6 @@ module.exports = function(options, repo, params, id, dataResolver) {
var type = source.type;
Object.assign(source, info);
source.type = type;
source.basename = name;
source.tiles = [
// meta url which will be detected when requested
'mbtiles://' + name + '/{z}/{x}/{y}.' + (info.format || 'pbf')
@@ -232,16 +230,18 @@ module.exports = function(options, repo, params, id, dataResolver) {
if (source.format == 'pbf') {
map.sources[name].emptyTile = new Buffer(0);
} else {
var color = new Color(source.color || '#fff');
var color = new Color(source.color || 'rgba(255,255,255,0)');
var format = source.format;
if (format == 'jpg') {
format = 'jpeg';
}
sharp(new Buffer(color.rgbArray()), {
var array = color.array();
var channels = array.length == 4 && format != 'jpeg' ? 4 : 3;
sharp(new Buffer(array), {
raw: {
width: 1,
height: 1,
channels: 3
channels: channels
}
}).toFormat(format).toBuffer(function(err, buffer, info) {
map.sources[name].emptyTile = buffer;

View File

@@ -16,7 +16,7 @@ module.exports = function(options, repo, params, id, reportTiles, reportFont) {
Object.keys(styleJSON.sources).forEach(function(name) {
var source = styleJSON.sources[name];
var url = source.url;
if (url.lastIndexOf('mbtiles:', 0) === 0) {
if (url && url.lastIndexOf('mbtiles:', 0) === 0) {
var mbtilesFile = url.substring('mbtiles://'.length);
var fromData = mbtilesFile[0] == '{' &&
mbtilesFile[mbtilesFile.length - 1] == '}';
@@ -29,19 +29,17 @@ module.exports = function(options, repo, params, id, reportTiles, reportFont) {
}
});
var findFontReferences = function(obj) {
Object.keys(obj).forEach(function(key) {
var value = obj[key];
if (key == 'text-font') {
if (value && value.length > 0) {
value.forEach(reportFont);
}
} else if (value && typeof value == 'object') {
findFontReferences(value);
styleJSON.layers.forEach(function(obj) {
if (obj['type'] == 'symbol') {
var fonts = (obj['layout'] || {})['text-font'];
if (fonts && fonts.length) {
fonts.forEach(reportFont);
} else {
reportFont('Open Sans Regular');
reportFont('Arial Unicode MS Regular');
}
});
};
styleJSON.layers.forEach(findFontReferences);
}
});
var spritePath;

View File

@@ -12,7 +12,7 @@ var base64url = require('base64url'),
cors = require('cors'),
express = require('express'),
handlebars = require('handlebars'),
mercator = new (require('sphericalmercator'))(),
mercator = new (require('@mapbox/sphericalmercator'))(),
morgan = require('morgan');
var packageJson = require('../package'),
@@ -36,10 +36,7 @@ module.exports = function(opts, callback) {
styles: {},
rendered: {},
data: {},
fonts: { // default fonts, always expose these (if they exist)
'Open Sans Regular': true,
'Arial Unicode MS Regular': true
}
fonts: {}
};
app.enable('trust proxy');
@@ -141,10 +138,7 @@ module.exports = function(opts, callback) {
}
});
if (Object.keys(serving.styles).length > 0) {
// serve fonts only if serving some styles
app.use('/fonts/', serve_font(options, serving.fonts));
}
app.use('/', serve_font(options, serving.fonts));
Object.keys(data).forEach(function(id) {
var item = data[id];
@@ -175,8 +169,13 @@ module.exports = function(opts, callback) {
var addTileJSONs = function(arr, req, type) {
Object.keys(serving[type]).forEach(function(id) {
var info = clone(serving[type][id]);
info.tiles = utils.getTileUrls(req, info.tiles,
type + '/' + id, info.format);
var path = '';
if (type == 'rendered') {
path = 'styles/' + id + '/rendered';
} else {
path = type + '/' + id;
}
info.tiles = utils.getTileUrls(req, info.tiles, path, info.format);
arr.push(info);
});
return arr;
@@ -337,6 +336,10 @@ module.exports = function(opts, callback) {
return callback();
});
process.on('SIGINT', function() {
process.exit();
});
setTimeout(callback, 1000);
return {
app: app,

View File

@@ -18,7 +18,7 @@ var testTileJSONArray = function(url) {
});
};
var testTileJSON = function(url, basename) {
var testTileJSON = function(url) {
describe(url + ' is TileJSON', function() {
it('is json', function(done) {
supertest(app)
@@ -27,11 +27,10 @@ var testTileJSON = function(url, basename) {
.expect('Content-Type', /application\/json/, done);
});
it('has valid basename and tiles', function(done) {
it('has valid tiles', function(done) {
supertest(app)
.get(url)
.expect(function(res) {
res.body.basename.should.equal(basename);
res.body.tiles.length.should.be.greaterThan(0);
}).end(done);
});
@@ -64,6 +63,6 @@ describe('Metadata', function() {
});
});
testTileJSON('/styles/test-style/rendered.json', 'test-style');
testTileJSON('/data/openmaptiles.json', 'openmaptiles');
testTileJSON('/styles/test-style/rendered.json');
testTileJSON('/data/openmaptiles.json');
});