一、GeoServer+OpenLayers调用WMTS、Vector Tile服务
1、WMTS服务
//切片名
var gridNames = ['EPSG:4326:0', 'EPSG:4326:1', 'EPSG:4326:2', 'EPSG:4326:3', 'EPSG:4326:4', 'EPSG:4326:5', 'EPSG:4326:6', 'EPSG:4326:7', 'EPSG:4326:8', 'EPSG:4326:9', 'EPSG:4326:10', 'EPSG:4326:11', 'EPSG:4326:12', 'EPSG:4326:13', 'EPSG:4326:14', 'EPSG:4326:15', 'EPSG:4326:16', 'EPSG:4326:17', 'EPSG:4326:18', 'EPSG:4326:19', 'EPSG:4326:20', 'EPSG:4326:21'];
//切片大小
var resolutions = [0.703125, 0.3515625, 0.17578125, 0.087890625, 0.0439453125, 0.02197265625, 0.010986328125, 0.0054931640625, 0.00274658203125, 0.001373291015625, 6.866455078125E-4, 3.4332275390625E-4, 1.71661376953125E-4, 8.58306884765625E-5, 4.291534423828125E-5, 2.1457672119140625E-5, 1.0728836059570312E-5, 5.364418029785156E-6, 2.682209014892578E-6, 1.341104507446289E-6, 6.705522537231445E-7, 3.3527612686157227E-7];
//设置地图投影
var projection = new ol.proj.Projection({
code: 'EPSG:4326',//投影编码
units: 'degrees',
axisOrientation: 'neu'
});
//OSM地图
var osmMap = new ol.layer.Tile({
source: new ol.source.OSM()
});
//地图
var map = new ol.Map({
layers: [
osmMap,
new ol.layer.Tile({
source: new ol.source.WMTS({
url: 'http://IP:端口/geoserver/gwc/service/wmts', //服务地址
layer: 'layer_name',
//切片集
matrixSet: 'EPSG:4326',
format: 'image/png',
projection: projection,
//切片信息
tileGrid: new ol.tilegrid.WMTS({
tileSize: [256, 256],
extent: [-180.0, -90.0, 180.0, 90.0],//范围
origin: [-180.0, 90.0],
resolutions: resolutions,
matrixIds: gridNames,
}),
})
})
]
});
map.getView().fit(bounds, map.getSize());
2、Vector Tile服务
var layer = 'opengeo:countries';
var projection_epsg_no = '900913';
var map = new ol.Map({
target: 'map',
view: new ol.View({
center: [0, 0],
zoom: 2
}),
layers: [new ol.layer.VectorTile({
style:simpleStyle,
source: new ol.source.VectorTile({
tilePixelRatio: 1, // oversampling when > 1
tileGrid: ol.tilegrid.createXYZ({maxZoom: 19}),
format: new ol.format.MVT(),
url: '/geoserver/gwc/service/tms/1.0.0/' + layer +
'@EPSG%3A'+projection_epsg_no+'@pbf/{z}/{x}/{-y}.pbf'
})
})
]
二、瓦片行列号
1、影像金字塔
影像金字塔由原始影像按一定规则生成的由细到粗不同分辨率的影像集。金字塔的底部是图像的高分辨率表示,也就是原始图像,而顶部是低分辨率的近似。最底层的分辨率最高,并且数据量最大,随着层数的增加,其分辨率逐渐降低,数据量也按比例减少。
指在同一的空间参照下,根据用户需要以不同分辨率进行存储与显示,形成分辨率由粗到细、数据量由小到大的金字塔结构。影像金字塔结构用于图像编码和渐进式图像传输,是一种典型的分层数据结构形式,适合于栅格数据和影像数据的多分辨率组织,也是一种栅格数据或影像数据的有损压缩方式。
三、基本操作
在浏览器中打开 GeoServer 界面,使用用户名“admin”和密码“geoserver”登录。管理界面将会显示。
Data 数据 面板中的 Layer Preview 可以用于预览服务数据,可以用 OpenLayers 开启示例数据的显示。
四、矢量切片(vector tiles)
矢量切片的优点:
- 数据在客户端渲染,而不是在服务器端。允许不同的地图应用程序使用不同的样式去渲染一个地图。
- 矢量切片的大小通常比图片瓦片小,这可以使得数据传输得更快以及使用更低的带宽。
- GeoServer内嵌的GeoWebCache可以有效地存储矢量切片数据,只需要存储一个矢量切片就能在客户端配置不同的样式。
- 在客户端获取数据,可以绘制分辨率很高的地图
- 客户端可以本地访问实际的要素信息(属性信息和几何信息),可以进行非常复杂和精细的要素渲染。
缺点——需要对地理数据进行预处理,以便客户端能够完成所需的绘图(类似于图像瓦片地图的预处理数据)。
1、矢量切片格式
GeoServer可以生成三种格式的矢量切片:GeoJSON,TopoJSON,MapBox Vector(MVT)。
MVT是生产环境中首选的矢量切片格式。
2、矢量切片插件
GeoServer的矢量切片插件是官方的插件,可以在GeoServer download页面中下载。
(1)下载和你的GeoServer版本对应的矢量切片插件。
注意:一定要版本对应。
(2)将下载的内容解压(jar包)并复制到GeoServer的WEB-INF/lib文件夹下。
(3) 重新启动GeoServer。
验证矢量切片扩展是否已安装成功:
(1)打开GeoServer的Web管理界面。
(2)单击"图层"并随意选择一个矢量图层。
(3)点击"TileCaching"面板.
(4)滚动页面到"Tile Image Formats"部分,除了标准的GIF/PNG/JPEG格式之外,你还应该看到以下内容:
如果看到了这些选项,那么就表示矢量切片的插件已经安装成功了。
五、Openlayers 3加载XYZ示例
Openlayers3中的ol.source.XYZ类可以加载Tile瓦片图层
1、基础XYZ-谷歌离线切片
观察这些图片命名,xyz是很明显的,这是下载的谷歌切片,直接加载如下:
var layer= new ol.layer.Tile({
source : new ol.source.XYZ({
url : 'http://localhost:8080/baseMap/{z}/{x}/{y}.png'
})
});
2、GeoWebCache切片
var road= new ol.layer.Tile({
source : new ol.source.XYZ({
tileUrlFunction :function (xyz, obj1, obj2) {
if (!xyz) return "";
var z=xyz[0];
var x=Math.abs(xyz[1]);
var y=Math.abs(xyz[2]);
var xyz_convert= convert_(z,x,y);
x=xyz_convert[0];
y=xyz_convert[1];
z=xyz_convert[2];
var shift = z / 2;
var half = 2 << shift;
var digits = 1;
if (half > 10)
digits = parseInt(Math.log(half)/Math.log(10)) + 1;
var halfx = parseInt(x / half);
var halfy = parseInt(y / half);
x=parseInt(x);
y=parseInt(y)+1;
var url=tileRoot+"/EPSG_900913"+"_"+padLeft_(2,z)+"/"+padLeft_(digits,halfx)+"_"+padLeft_(digits,halfy)+"/"+padLeft_(2*digits,x)+"_"+padLeft_(2*digits,y)+"."+format;
return url;
}
})
});
//字符截取
var padLeft_ = function(num, val) {
return (new Array(num).join('0') + val).slice(-num);
};
//xy行列转换
var convert_=function(zoomLevel, x, y) {
var extent = Math.pow(2, zoomLevel);
if (x < 0 || x > extent - 1) {
console.log("The X coordinate is not sane: " + x);
return;
}
if (y < 0 || y > extent - 1) {
console.log("The Y coordinate is not sane: " + y);
return;
}
var gridLoc = [x, extent - y - 1, zoomLevel];
return gridLoc;
}