MapServer UTFGrid + OpenLayers 3
Добавлено: 01 ноя 2016, 10:10
MapServer начиная с 7 версии умеет отдавать данные в формате UTFGrid, подробнее. Так вот, очень часто возникает вопрос о том, как этим вообще пользоваться, например, в связке с OpenLayers 3. И хотя на сайте OpenLayers есть пример подключения UTFGrid, всё равно остаётся ряд моментов, которые требуется прояснить дополнительно.
1. TileJSON. Согласно документации за поддержку UTFGrid со стороны OpenLayers отвечает класс ol.source.TileUTFGrid (Layer source for UTFGrid interaction data loaded from TileJSON format). Мы видим, что тут возникает упоминание некоего TileJSON формата, с которым большинству до этого сталкиваться не приходилось. Что же это за формат? А это очередное изобретение Mapbox, представляющее собой формат описания тайловых наборов, репозиторий. Всё что нам пока нужно знать - это то, что в этом формате можно описать URL-ы до обычных тайлов и до тайлов UTFGrid, например:
2. MapServer Tile Mode. Как видно из предыдущего пункта нам каким-то образом нужно научить отдавать MapServer UTFGrid по переданным значениям xyz. MapServer умеет это делать с помощью режима Tile Mode о чём я писал тут. Единственная проблема - если один и тот же mapfile используется у нас и для обычных (растровых) и для UTFGrid тайлов, то как указать нужный формат в запросе? На помощь приходит возможность MapServer передавать значения переменных через URL. Предположим, что у нас есть mapfile utfgrid.map следующего содержания (кстати, вполне рабочий): Тогда TileJSON описание (поместим его, например, в файл tile.json, а сам файл разместим на веб сервере) будет иметь вид:
3. OpenLayers. Пример подключения в OpenLayers:
В данном случае при подключении слоя gridLayer на карту - для каждого растрового тайла автоматически загрузятся UTFGrid описания, которые для примера мы выводим в консоль по клику на карте.
Важно. Растровые тайлы и UTFGrid не связаны между собой ничем, кроме как адресацией xyz. То есть в данном примере наш TileJSON файл мог не содержать секцию "tiles", в этом случае мы бы просто подключали растровые тайлы не через ol.source.TileJSON, а, например, через ol.source.XYZ.
UPD.: как мне тут подсказывают - в случае с ol.source.TileUTFGrid можно не создавать отдельный файл tile.json, а передать его параметры непосредственно при инициализации хранилища:
1. TileJSON. Согласно документации за поддержку UTFGrid со стороны OpenLayers отвечает класс ol.source.TileUTFGrid (Layer source for UTFGrid interaction data loaded from TileJSON format). Мы видим, что тут возникает упоминание некоего TileJSON формата, с которым большинству до этого сталкиваться не приходилось. Что же это за формат? А это очередное изобретение Mapbox, представляющее собой формат описания тайловых наборов, репозиторий. Всё что нам пока нужно знать - это то, что в этом формате можно описать URL-ы до обычных тайлов и до тайлов UTFGrid, например:
Код: Выделить всё
{
"version": "1.0.0",
"tiles": [
"https://a.tiles.mapbox.com/v4/mapbox.geography-class/{z}/{x}/{y}.png",
"https://b.tiles.mapbox.com/v4/mapbox.geography-class/{z}/{x}/{y}.png"
],
"grids": [
"https://a.tiles.mapbox.com/v4/mapbox.geography-class/{z}/{x}/{y}.grid.json",
"https://b.tiles.mapbox.com/v4/mapbox.geography-class/{z}/{x}/{y}.grid.json"
]
}
Код: Выделить всё
MAP
IMAGETYPE UTFGRID
SIZE 2000 2000
EXTENT 75.0819396972656 49.0830841064453 89.8699798583984 57.2502746582031
NAME geosample
PROJECTION
"init=epsg:4326"
END
OUTPUTFORMAT
NAME "png"
EXTENSION "png"
MIMETYPE "image/png"
DRIVER AGG/PNG
IMAGEMODE RGBA
FORMATOPTION "INTERLACE=OFF"
END
OUTPUTFORMAT
NAME "utfgrid"
MIMETYPE "application/json"
DRIVER UTFGRID
EXTENSION "json"
FORMATOPTION "UTFRESOLUTION=4"
FORMATOPTION "DUPLICATES=false"
END
LAYER
CONNECTIONTYPE postgis
NAME admin
CONNECTION "host=gis-lab.info dbname=geosample user=guest password=guest"
DATA "the_geom from admin using srid=4326"
TYPE POLYGON
UTFITEM gid
UTFDATA "{\"gid\":\"[id]\",\"name\":\"[name]\"}"
CLASS
NAME admin
STYLE
COLOR 100 100 100
END
END
END
END
Код: Выделить всё
{
"version": "2.1.0",
"tiles": [
"http://localhost:8001/cgi-bin/mapserv?map=utfgrid.map&layers=admin&mode=tile&tile={x}+{y}+{z}&tilemode=gmap&map.imagetype=png"
],
"grids": [
"http://localhost:8001/cgi-bin/mapserv?map=utfgrid.map&layers=admin&mode=tile&tile={x}+{y}+{z}&tilemode=gmap&map.imagetype=utfgrid"
]
}
Код: Выделить всё
var mapLayer = new ol.layer.Tile({
source: new ol.source.TileJSON({
url: 'http://localhost:8001/tile.json'
})
});
var gridSource = new ol.source.TileUTFGrid({
url: "http://localhost:8001/tile.json"
});
var gridLayer = new ol.layer.Tile({source: gridSource});
var map = new ol.Map({
layers: [mapLayer, gridLayer],
target: 'map',
view: new ol.View({
center: [9449777.3, 6914882.51],
zoom: 7
})
});
map.on('click', function(evt) {
var viewRes = map.getView().getResolution();
gridSource.forDataAtCoordinateAndResolution(evt.coordinate, viewRes, function (data) {
console.log(data);
});
});
Важно. Растровые тайлы и UTFGrid не связаны между собой ничем, кроме как адресацией xyz. То есть в данном примере наш TileJSON файл мог не содержать секцию "tiles", в этом случае мы бы просто подключали растровые тайлы не через ol.source.TileJSON, а, например, через ol.source.XYZ.
UPD.: как мне тут подсказывают - в случае с ol.source.TileUTFGrid можно не создавать отдельный файл tile.json, а передать его параметры непосредственно при инициализации хранилища:
Код: Выделить всё
var gridSource = new ol.source.TileUTFGrid({
tileJSON: {
"version": "2.1.0",
"tiles": ["http://localhost:8001/cgi-bin/mapserv?map=utfgrid.map&layers=admin&mode=tile&tile={x}+{y}+{z}&tilemode=gmap&map.imagetype=png"],
"grids": ["http://localhost:8001/cgi-bin/mapserv?map=utfgrid.map&layers=admin&mode=tile&tile={x}+{y}+{z}&tilemode=gmap&map.imagetype=utfgrid"]
}
});