Geoserver2.11矢量切片与OL3中的调用展示

概述:

本文讲述在Geoserver2.11中如何进行矢量切片以及OL3中的调用展示。

矢量切片简介:

一、提出

GIS的底图一直使用金字塔技术进行切图,使用户能够快速访问指定级别的地图或者影像。但是切图本身是一张图片,无法进行交互。于是又引入了矢量图层用来显示矢量点线面,这通常需要先获取矢量地理数据,然后通过前端将其绘制成不同元素便能通过鼠标进行响应交互了。

这种GIS组织方式在数据量比较小的时候并没有什么大问题,但是在数据量比较大时(例如全国的详细街区数据)存在以下几个问题。

1、同一套数据的展示在不同的需求下可能需要不同的样式(例如,白天和夜间模式)而对于传统栅格切片对此需求必须重新进行切片;

2、由于切片的分辨率固定,分辨率过高切片体积过大,分辨率过低高清屏无法清晰显示。

3、矢量数据的请求如果是按需请求每次都向服务器请求数据加重服务器压力,如果一次请求按需展示,当矢量数据过大时(例如全国的水系数据)对于前端的压力过大。

二、矢量切片的定义

矢量切片是一种利用协议缓冲(Protocol Buffers)技术的紧凑的二进制格式用来传递信息。当渲染地图时矢量切片使用一系列储存的内部数据进行制图。被组织到矢量切片的图层(比如道路、水、区域),每一层都有包含几何图形和可变属性的独立要素(例如姓名、类型等等)。通俗的说,就是将矢量数据以建立金字塔的方式,像栅格切片那样分割成一个一个描述性文件,以GeoJson格式或者以pbf等自定义格式组织,然后在前端根据显示需要按需请求不同的矢量瓦片数据进行Web绘图。

三、常见格式

GeoJson、TopoJson、pbf(Arcgis格式)、KML、 GeoRSS等

四、优势

矢量切片的优势

五、栅格切片与矢量切片的对比

矢量切片

栅格切片

Geoserver中矢量切片的发布:

在geoserver中可发布单个图层,也可发布一个图层组,上述的示例是发布的一个图层组。

1、选择发布图层(组)

选择发布图层组

2、切换到“Tile Cache”面板,设置切片参数

设置切片参数

设置切片网格

注意:

1、切片网格系统默认了几个,也是可以自定义的,具体的设置为GridSets->Create a new gridset。

设置切片网格

OL3的调用与展示:

1、代码

<!DOCTYPE html>
<html>
<head>
    <title>GeoJSON切片</title>
    <link rel="stylesheet" href="css/ol.css" type="text/css">
    <script src="js/ol.js"></script>
	<script src="js/jquery-1.8.3.js"></script>
    <style>
		body,html,#map{
			padding:0px;
			margin:0px;
			height:100%;
			overflow:hidden;
			background:#ffffff;
		}
		.ol-mouseposition{
			position:absolute;
			bottom:20px;
			left:45%;
			padding:5px;
			background:#fff;
			border:1px solid #ccc;
			font-size:12px;
		}
		ul{
        	list-style: none;
        	position: absolute;
        	right:10px;
        	top:10px;
        	font-size: 14px;
			z-index:99;
        }
        ul li{
        	line-height: 28px;
        	height: 28px;
        	text-align: center;
        	width:40px;
        	float:left;
			cursor:pointer;
			background: #ffffff;
        }
        ul li.active{
        	background: #007AC2;
        	opacity: 0.8;
        	color:#ffffff;
        }
        ul li.day{
        	border:1px solid #007AC2;
        	border-right: none;
        	border-top-left-radius: 3px;
        	border-bottom-left-radius: 3px;
        }
        ul li.night{
        	border:1px solid #007AC2;
        	border-left: none;
        	border-top-right-radius: 3px;
        	border-bottom-right-radius: 3px;
        }
    </style>
</head>
<body>
	<ul id="lyrstyle">
		<li class="day active">白天</li>
		<li class="night">黑夜</li>
	</ul>
    <div id="map" class="map" tabindex="0"></div>
    <script>
		var projection4326 = new ol.proj.Projection({
			code: 'EPSG:4326',
			units: 'degrees',
		});
		var lyr = "lzugis:china";
		var dayStyle = function(feature,resolution){
			var stroke = new ol.style.Stroke({color: "rgba(0,0,255,0.4)", width: 2});
			var fill = new ol.style.Fill({color:"rgba(0,0,255,0)"});				
			var lyr = feature.f.split(".")[0];
			if(lyr=="province"){
				return new ol.style.Style({
					fill: fill,
					stroke: stroke
				});
			}
			else{
				var name = feature.get("name");
				return new ol.style.Style({
					image: new ol.style.Circle({
						radius: 5,
						fill: new ol.style.Fill({
							color: 'rgba(0,0,255,0.4)'
						})
					}),
					text: new ol.style.Text({ //文本样式
						font: '15px Calibri,sans-serif',
						fill: new ol.style.Fill({
							color: '#000000'
						}),
						text:name,
						offsetX:0,
						offsetY:12
					})
				});
			}
		};
		var nightStyle = function(feature,resolution){
			var stroke = new ol.style.Stroke({color: "rgba(255,255,255,0.4)", width: 2});
			var fill = new ol.style.Fill({color:"rgba(0,0,0,0.8)"});				
			var lyr = feature.f.split(".")[0];
			if(lyr=="province"){
				return new ol.style.Style({
					fill: fill,
					stroke: stroke
				});
			}
			else{
				var name = feature.get("name");
				return new ol.style.Style({
					image: new ol.style.Circle({
						radius: 5,
						fill: new ol.style.Fill({
							color: 'rgba(255,255,255,1)'
						})
					}),
					text: new ol.style.Text({ //文本样式
						font: '15px Calibri,sans-serif',
						fill: new ol.style.Fill({
							color: '#ffffff'
						}),
						text:name,
						offsetX:0,
						offsetY:12
					})
				});
			}
		};
		// 行政区划图层
		var vector = new ol.layer.VectorTile({
			// 矢量切片的数据源
			source: new ol.source.VectorTile({
				projection: projection4326,
				format: new ol.format.GeoJSON(),
				tileGrid: ol.tilegrid.createXYZ({
					extent: ol.proj.get('EPSG:4326').getExtent(),
					maxZoom: 22
				}),
				tilePixelRatio: 1,
				// 矢量切片服务地址
				tileUrlFunction: function(tileCoord){
					return 'http://127.0.0.1:8088/geoserver/gwc/service/tms/1.0.0/'
						+lyr+'@EPSG%3A4326@geojson/'+(tileCoord[0]-1)
						+ '/'+tileCoord[1] + '/' + (Math.pow(2,tileCoord[0]-1)+tileCoord[2]) + '.geojson';
				}			
			}),
			style:dayStyle
		});
		var tiled = new ol.layer.Tile({
			visible: true,
			source: new ol.source.TileWMS({
				url: 'http://localhost:8088/geoserver/lzugis/wms',
				params: {'FORMAT': 'image/png', 
					'VERSION': '1.1.1',
					tiled: true,
					STYLES: '',
					LAYERS: 'lzugis:province',
					tilesOrigin: 73.4510046356223 + "," + 18.1632471876417
				}
			})
		  });
        var map = new ol.Map({
            layers: [
				//tiled,
				vector
			],
            target: 'map',
            controls: ol.control.defaults().extend([
                new ol.control.MousePosition({
					className:"ol-mouseposition",
					coordinateFormat: ol.coordinate.createStringXY(5)
				})
            ]),
            view: new ol.View({
                projection: projection4326,
				minZoom:4,
				maxZoom:18,
                center: [103.2921875, 38.581640625],
                zoom: 4
            })
        });
		
		$("#lyrstyle li.day").on("click",function(){
			$("#lyrstyle li").removeClass("active");
			$(this).addClass("active");
			vector.setStyle(dayStyle);
			var zoom = map.getView().getZoom();
			map.getView().setZoom(zoom-1);
			$("#map").css("background","#ffffff");
		});
		$("#lyrstyle li.night").on("click",function(){
			$("#lyrstyle li").removeClass("active");
			$(this).addClass("active");
			vector.setStyle(nightStyle);
			var zoom = map.getView().getZoom();
			map.getView().setZoom(zoom+1);
			$("#map").css("background","rgba(0,0,0,0.8)");
		});
    </script>
</body>
</html>

2、运行效果

从上图看出,可以很方便的对地图的风格样式进行重新定义。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Coding迪斯尼

VUE+WebPack游戏设计:实现盒子爆破效果和界面美化

1613
来自专栏BestSDK

shift键在Excel中,还有这10种变态玩法?

电脑键盘上有很多「瑞士军刀」似的按键,掌握这些按键的使用技巧,你让你在Excel操作中,如虎添翼。 SHIFT键就是其中之一。 Excel中的技巧有很多,基本都...

4037
来自专栏前端黑板报

canvas-入门

定义 canvas是HTML5新增的一个重要元素,先看下它的定义: <canvas> is an HTML element which can be used ...

22210
来自专栏coding for love

CSS进阶09-定位体系差异分析

(注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!) (注2:更多内容请查看我的目录。)

963
来自专栏非典型技术宅

iOS动画系列之六:利用CABasic Animation完成带动画特效的登录界面1. 画风突变的笑脸2. 心跳3. iOS实践:实现一个带动效的登录界面

1356
来自专栏MasiMaro 的技术博文

对话框伸缩功能的实现

对话框的伸缩功能是指当触发某一操作时只显示部分对话框的内容,再次触发时显示全部的对话框范围,就比如画图软件上的选择颜色对话框,我们可以使用系统预定义的颜色,也可...

1092
来自专栏州的先生

丑拒!如何在Python中编写精美图形界面

在默认情况下,我们使用PyQt5创建出来的窗口和部件都是默认的样式,虽然谈不上很丑,但是也毫无美感可言。

6.9K4
来自专栏偏前端工程师的驿站

CSS魔法堂:再次认识font

一、前言                                 文字承载着站点内涵,而良好的字体、排版则为用户提供舒适的阅读体验。本文打算对字体稍微深...

27510
来自专栏IMWeb前端团队

重构不完全教程集之二

本文作者:IMWeb 结一原文出处:IMWeb社区未经同意,禁止转载 故不登高山,不知天之高也;不临深溪,不知地之厚也。--摘自《劝学》 ::before &...

24010
来自专栏服务端技术杂谈

iOS 开发从 UIView 动画说起

毋庸置疑的:在iOS开发中,制作动画效果是最让开发者享受的环节之一。一个设计严谨、精细的动画效果能给用户耳目一新的效果,吸引他们的眼光 —— 这对于app而言是...

3837

扫码关注云+社区