自托管Mapbox矢量图块


81

正如在FOSS4G上的演讲中所介绍的那样,Mapbox Studio允许创建Mapbox矢量图块并将其导出为.mbtiles文件。

所述mapbox-gl.js库可以被用于动态风格和渲染在客户端(浏览器)侧Mapbox矢量瓷砖。

缺少的部分:如何自托管Mapbox矢量图块(.mbtiles),以便可以通过mapbox-gl.js使用它们?

我知道Mapbox Studio可以将矢量图块上传到Mapbox服务器,并让其托管图块。但这对我来说是没有选择的,我想将矢量切片托管在自己的服务器上。


事实证明,下面的TileStream方法是死胡同。请参阅我的答案以获取Tilelive的有效解决方案。


我尝试了TileStream,它可以从.mbtiles文件中提供图像切片:

我的网页使用mapbox-gl v0.4.0:

<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.4.0/mapbox-gl.css' rel='stylesheet' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.4.0/mapbox-gl.js'></script>

并在JavaScript脚本中创建mapboxgl.Map:

  var map = new mapboxgl.Map({
    container: 'map',
    center: [46.8104, 8.2452],
    zoom: 9,
    style: 'c.json'
  });

c.json样式文件配置矢量瓦来源:

{
  "version": 6,
  "sprite": "https://www.mapbox.com/mapbox-gl-styles/sprites/bright",
  "glyphs": "mapbox://fontstack/{fontstack}/{range}.pbf",
  "constants": {
    "@land": "#808080",
    "@earth": "#805040",
    "@water": "#a0c8f0",
    "@road": "#000000"
  },
  "sources": {
    "osm_roads": {
      "type": "vector",
      "url": "tile.json"
    }
  },
  "layers": [{
    "id": "background",
    "type": "background",
    "paint": {
      "background-color": "@land"
    }
  }, {
    "id": "roads",
    "type": "line",
    "source": "osm_roads",
    "source-layer": "roads",
    "paint": {
      "line-color": "@road"
    }
  }]
}

...在中具有以下TileJSON规范tile.json

{
  "tilejson": "2.1.0",
  "tiles": [
    "http://localhost:8888/v2/osm_roads/{z}/{x}/{y}.png"
  ],
  "minzoom": 0,
  "maxzoom": 12
}

...指向运行在的我的TileStream服务器localhost:8888。TileStream已开始于:

node index.js start --tiles="..\tiles"

... ..\tiles文件夹中包含我的osm_roads.mbtiles文件的位置。

使用此设置,我可以打开我的网页,但只能看到背景层。在浏览器网络跟踪中,我可以看到在放大时确实加载了图块,但是浏览器JavaScript错误控制台包含几种形式的错误

Error: Invalid UTF-8 codepoint: 160      in mapbox-gl.js:7

由于矢量切片不是.png图像而是ProtoBuf文件,因此切片URL http://localhost:8888/v2/osm_roads/{z}/{x}/{y}.pbf实际上更有意义,但这是行不通的。

有任何想法吗?

Answers:


53

正如@Greg指出的那样,您应该使用Tilelive来托管自己的矢量图块,而不是TileStream(我的第一次尝试)。

Tilelive本身不是服务器,而是后端框架,用于处理来自不同来源的不同格式的图块。但是它基于Node.js,因此您可以以一种非常简单的方式将其转变为服务器。要从.mbtilesMapbox Studio导出的来源中读取图块,您需要使用node-mbtiles tilelive模块。

旁注:当前Mapbox Studio 在Windows和OS X下存在一个错误,该错误阻止导出的.mbtiles文件显示在您选择的目标位置。解决方法:只需在中获取最新export-xxxxxxxx.mbtiles文件~/.mapbox-studio/cache

我发现了两个服务器实现(alexbirkett的ten20 tile服务器hanchao的TileServer)都使用Express.js作为Web应用程序服务器。

这是我的简约方法,大致基于这些实现:

  1. 安装Node.js
  2. 抓取节点包 npm install tilelive mbtiles express
  3. 在文件中实现服务器server.js

    var express = require('express');
    var http = require('http');
    var app = express();
    var tilelive = require('tilelive');
    require('mbtiles').registerProtocols(tilelive);
    
    //Depending on the OS the path might need to be 'mbtiles:///' on OS X and linux
    tilelive.load('mbtiles://path/to/osm_roads.mbtiles', function(err, source) {
    
        if (err) {
            throw err;
        }
        app.set('port', 7777);
    
        app.use(function(req, res, next) {
            res.header("Access-Control-Allow-Origin", "*");
            res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
            next();
        });
    
        app.get(/^\/v2\/tiles\/(\d+)\/(\d+)\/(\d+).pbf$/, function(req, res){
    
            var z = req.params[0];
            var x = req.params[1];
            var y = req.params[2];
    
            console.log('get tile %d, %d, %d', z, x, y);
    
            source.getTile(z, x, y, function(err, tile, headers) {
                if (err) {
                    res.status(404)
                    res.send(err.message);
                    console.log(err.message);
                } else {
                  res.set(headers);
                  res.send(tile);
                }
            });
        });
    
        http.createServer(app).listen(app.get('port'), function() {
            console.log('Express server listening on port ' + app.get('port'));
        });
    });

    注意:Access-Control-Allow-...标头启用跨域资源共享(CORS),因此从其他服务器提供服务的网页可以访问图块。

  4. 运行它 node server.js

  5. 在以下位置使用Mapbox GL JS设置网页minimal.html

    <!DOCTYPE html >
    <html>
      <head>
        <meta charset='UTF-8'/>
        <title>Mapbox GL JS rendering my own tiles</title>
        <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.4.0/mapbox-gl.css' rel='stylesheet' />
        <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.4.0/mapbox-gl.js'></script>
        <style>
          body { margin:0; padding:0 }
          #map { position:absolute; top:0; bottom:50px; width:100%; }
        </style>
      </head>
      <body>
        <div id='map'>
        </div>
        <script>
          var map = new mapboxgl.Map({
            container: 'map',
            center: [46.8, 8.5],
            zoom: 7,
            style: 'minimal.json'
          });
        </script>
      </body>
    </html>
  6. 指示图块源的位置,并使用以下样式设置图层的样式minimal.json

    {
      "version": 6,
      "constants": {
        "@background": "#808080",
        "@road": "#000000"
      },
      "sources": {
        "osm_roads": {
          "type": "vector",
          "tiles": [
            "http://localhost:7777/v2/tiles/{z}/{x}/{y}.pbf"
          ],
          "minzoom": 0,
          "maxzoom": 12
        }
      },
      "layers": [{
        "id": "background",
        "type": "background",
        "paint": {
          "background-color": "@background"
        }
      }, {
        "id": "roads",
        "type": "line",
        "source": "osm_roads",
        "source-layer": "roads",
        "paint": {
          "line-color": "@road"
        }
      }]
    }
  7. 服务网页并欢喜。


2
请注意,您需要使用以下三个///文件来定义mbtiles文件:tilelive.load('mbtiles://path/to/osm_roads.mbtiles', function(err, source) {
CDavis 2014年

@cdavis:这似乎取决于操作系统:///Linux和OS X需要三个,例如mbtiles:///usr/local/osm_roads.mbtiles。但是在Windows //上,如果您指定磁盘(例如),则只需两个mbtiles://D/data/osm_roads.mbtiles
Andreas Bilger 2014年

真的很有帮助,非常感谢,帮助我在5英尺内送达矢量mbtiles!
Bwyss

嗨,安德烈亚斯(Andreas)-我无法使用它-地图显示出来,但这只是一个大的空白灰色方块。我不确定您从哪里获得mbtiles信息。我尝试从tilemill导出一些默认mbtile。
mheavers 15-10-28

您似乎使用localhost:7777 / v2 / tiles /作为图块的位置,但是您从哪里得到该路径?或者,您需要做什么以确保导出的mbtiles文件将图像提供给该路径?
mheavers 15-10-28

26

自己托管矢量图块相对简单。MBTiles包含必须向Web公开的.pbf文件。而已。

可能最简单的方法是使用简单的开源服务器(例如TileServer-PHP)并将MBTiles文件与项目文件放置在同一文件夹中。TileServer为您完成所有托管配置(CORS,TileJSON,正确的gzip标头等)。安装意味着只需在启用PHP的Web服务器上解压缩即可。

如果要在笔记本电脑上启动TileServer-PHP,可以使用Docker。准备使用的容器位于DockerHub上。在Mac OS X和Windows下,它可以在几分钟内通过Kitematic图形用户界面运行:https ://kitematic.com/ 。在Kitematic中,只需搜索“ tileserver-php”,然后启动包含项目的随时可用的容器/虚拟机。然后单击“卷”并将MBTiles文件放入文件夹。您可以为您的矢量图块运行托管!

这样的矢量图块可以在MapBox Studio中作为源打开,或与MapBox GL JS WebGL查看器一起显示。

从技术上讲,甚至可以举办矢量瓷砖任何Web服务器上的一个普通文件夹或云存储,甚至GitHub上,如果你解压个别.pbf出MBtiles容器与像公用事业mbutil,设定CORS,TileJSON和gzip正确。Bellow是一个GitHub项目,也演示了这种方法。

尝试使用此查看器: MapBox GL JS查看器

并查看相关的回购协议:


1
对于我来说,到目前为止,这是上述所有选项中最简单的一种,感谢您的发帖。
mheavers 15-10-29

PGRestAPI,听起来不错,但对我而言安装失败。我永远无法成功安装PGRestAPI。因此,此php tile服务器是我唯一的选择,它可以完美运行。
hoogw

这是最有趣的,您能否详细说明如何正确设置CORS和TileJSON以提供pbf文件?我已经从download.geofabrik.de/europe下载了一个pbf文件,但是链接的项目包含许多包含许多pbf文件的目录。
php_nub_qq

12

我并不是在吹牛角,而是https://github.com/spatialdev/PGRestAPI是我一直在从事的一个项目,该项目托管从Mapbox Studio导出的.mbtiles矢量切片。

仍然需要大量文档,但基本上,请将.mbtiles文件拖放到/ data / pbf_mbtiles中,然后重新启动节点应用程序。它将通过该文件夹进行读取,并为您的矢量图块提供端点。

它还将通过/ data / shapefiles查找,并根据您的.shp动态创建动态Mapbox矢量图块。您也可以指向PostGIS实例并获取动态矢量切片。

我们将它们与https://github.com/SpatialServer/Leaflet.MapboxVectorTile结合使用,这是我们一直在研究的Leaflet / Mapbox矢量图块库。


1
PGRestAPI不再被积极开发不幸
拉斐尔

10

感谢您提出的重大问题。我不知道他们最终发布了矢量拼贴的稳定版本。此外,您可能必须使用此答案,因为它是“任何想法”的想法来源。题。我还没有工作室。

我认为您遇到的问题之一是您正在使用tilejson文件。您需要使用tilejson服务才能使用此类文件。因此,我认为您需要将“源”部分更改为嵌入式URL。尝试

"sources": {
"osm_roads": {
  "type": "vector",
  "url": "http://localhost:8888/v2/osm_roads/{z}/{x}/{y}.png"
 }
},

要么

"sources": { 
"osm_orads": {
  "type": "vector",
  "tiles": [
    "http://localhost:8888/v2/osm_roads/{z}/{x}/{y}.png"
  ],
  "minzoom": 0,
  "maxzoom": 12
 }
},

当它们mapbox://用作协议时,它是其服务的别名/速记符号。在视频的8:40附近简要讨论了“来源”部分。

新的矢量平铺过程的第一步是通过调整数据中所需的内容来整理矢量数据。另一步骤是将矢量数据带回MapBox Studio中并渲染数据/创建样式表。当您的c.json文件是样式表时,osm_roads将是第一步。您可能需要图块实时服务器来处理图块流,如视频15:01所述。该视频表明您需要xml文件中的其他元数据。

奇怪的是,您在其他地方引用了.pbf和样式表,但是您提供的url是根据矢量数据生成的结果tile .png文件。

如果您有MapBox键,则无需说。对于您自己的托管,我相信您将必须将github样式和字形复制到您自己的服务器上。再次注意,字形标记中有一个mapbox://协议。可能不需要这两个标记,因为您是通过图标来渲染普通线和多边形,而不是POI。值得一看。

最后,视频说明您可以将生成的矢量层带回工作室以对其进行样式设置。您可能要参考您的矢量图层,然后在工作室中首先应用id:background和id:roads样式。视频中说,实时直播是MapBox Studio幕后的服务器。这里的想法是确保在尝试提供动态渲染的最终矢量图块之前,已理解并修复了所有第二步问题。


好的,谢谢@Greg的想法。将会进一步调查并返回我的发现。
Andreas Bilger 2014年



1

超级超级,但现在GeoServer提供pbf(矢量切片格式)


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.