作者:小阳
1、序言
本文主要是利用了UTFGrid图层快速交互获取地物信息的特点,以SuperMap iClient for JavaScript的开发作为示范。(注:要实现本文所讲述的功能,同时需要SuperMap iServer和SuperMap iClient for JavaScript 7C系列及以上的版本才支持)。
在此之前,我先简要的讲一下什么是UTFGrid:UTFGrid只包含地物的属性信息,可以根据地物的屏幕像素位置在客户端快速获地物的属性信息, 如:实现鼠标悬停或鼠标单击某一地物时,快速获取该地物某些属性信息。UTFGrid可由iServer动态生成,也可以将其预先切成瓦片。详细了解UTFGrid(请参见或参见)
2、优化思路
1.使用分布式切图切属性瓦片缓存
这里要着重说一下UTFGrid单元格网大小的设置,这个值决定了UTFGrid的效率和精准度,设置的值越小精度越高,但是单元格也会越多,在一定程度上也会影响性能,怎样设置这个参数取决于地物的像素尺寸。首先,这个参数能被瓦片的大小整除,比如UTFGrid的瓦片大小为256x256,那么这个值就应该要被256整除。其次,我们需要参考地物在最小比例尺下的像素尺寸来设置(UTFGrid隐藏的情况下除外),如:在地图的最小比例尺下点符号的像素尺寸大概为8x8的大小,这里可以设置pixcell的值为8x8,在精度允许的情况下,这种情况推荐设置为16x16,因为8x8的单元格比较小,在监听鼠标事件时不易成功。
2.iServer启用属性瓦片缓存
默认发布的地图服务是没有启用 UTFGrid缓存的,需要进入到服务管理页面找到发布的地图服务,然后点击进入到缓存一栏勾选是否启用属性瓦片缓存。
iServer默认将UTFGrid瓦片放置在\webapps\iserver\output\sqlite路径下。
如果不启用属性瓦片缓存可以使用UTFGrid吗?答案是肯定的,如果是在大数据量的前提下,建议将UTFGrid预先切成瓦片,下图是各种方式使用UTFGrid的性能对比。
3.编程实现
初始化
var map,layer,vectorLayer,infowin,infowin1,highlightFea,popfeature,
host = document.location.toString().match(/file:\/\//)?"http://localhost:8090":‘http://‘ + document.location.host,
url="http://support.supermap.com.cn:8090/iserver/services/map-changchun/rest/maps/长春市区图_Local";
var controlmove,controlclick,utfgridPark,utfgridSchool;
function init(){
map = new SuperMap.Map("map", {controls: [
new SuperMap.Control.ScaleLine(),
new SuperMap.Control.Zoom(),
new SuperMap.Control.LayerSwitcher(),
new SuperMap.Control.Navigation({
dragPanOptions: {
enableKinetic: true
}
})],
projection: "EPSG:0",
//设置地图的最大范围,这行代码相当重要
maxExtent:new SuperMap.Bounds(48.4 , -7668.25,8958.85 , -55.58 )
});
layer = new SuperMap.Layer.TiledDynamicRESTLayer("China", url, {transparent: false}, {useCanvas: true, maxResolution: "auto",
scales:[1/2000,1/4000,1/8000,1/16000,1/32000]
});
vectorLayer=new SuperMap.Layer.Vector("Vector Layer");
//注意:pixcell与utfgridResolution两个属性有对应关系,在使用的时候也要注意场景;
//1.其中pixcell为发送给服务端请求utfgrid瓦片的精度,数值越小,精度越高,相应的瓦片大小也就越大;
//2.utfgridResolution为客户端解析瓦片使用的精度,应该与pixcell的值相等,否则会产生位置与属性对应不上的问题;
//3.通常如果UTFGrid图层为面图层,对应的数据量会比较大,为了不影响页面的正常浏览,可以将这两个属性设的大一些;
//4.isUseCache设置是否使用缓存,使用缓存能够提高性能;
utfgridSchool = new SuperMap.Layer.UTFGrid("UTFGridLayerSchool", url,
{
layerName: "[email protected]",
utfTileSize: 256,
pixcell: 16,
isUseCache: true
},
{
utfgridResolution: 16
});
utfgridSchool.maxExtent=layer.maxExtent;
utfgridPark = new SuperMap.Layer.UTFGrid("UTFGridLayerPark", url,
{
layerName: "[email protected]",
utfTileSize: 256,
pixcell: 16,
isUseCache: true
},
{
utfgridResolution: 16
});
utfgridPark.maxExtent=layer.maxExtent;
//监听move事件控件
controlmove = new SuperMap.Control.UTFGrid({
layers: [utfgridPark,utfgridSchool],
callback: callback,
handlerMode: "move"
});
//监听click事件控件
controlclick = new SuperMap.Control.UTFGrid({
layers: [utfgridPark,utfgridSchool],
callback: callback2,
});
layer.events.on({"layerInitialized": addLayer});
map.addControl(controlmove);
map.addControl(controlclick);
map.events.on({"zoomend":reviewUTFgrid});
}
function addLayer() {
var center = new SuperMap.LonLat(4539.98 , -3835.29);
map.addLayers([layer,vectorLayer,utfgridSchool,utfgridPark,]);
map.setCenter(center, 0);
reviewUTFgrid();
}
高亮点:在这里,我们利用了Control.UTFGrid监听move事件的方式,获取到点的坐标,然后绘制一个feature叠加到该点上实现高亮。如果想实现类似于百度地图每种类型的点都有不同的高亮图标方式,可以在feature的源数据属性表里面加字段来判断。实现效果如下:
//move事件回调函数
var callback = function (infoLookup) {
if(infowin)
map.removePopup(infowin);
if(highlightFea)
vectorLayer.removeFeatures(highlightFea);
if (infoLookup) {
var info;
for (var idx in infoLookup) {
info = infoLookup[idx];
if (info && info.data) {
var dom = "<div style=‘padding: 5px;padding-left:5px;font-size:12px;font-family:Microsoft YaHei;line-height:8px;color: black;background:lightgoldenrodyellow‘>" + info.data.name +"<br></br>"+"点击查看更多..."+ "</div>";
//设置x与y的像素偏移量,不影响地图浏览;
var xOff = (1 / map.getScale()) * 0.003;
var yOff = -(1 / map.getScale()) * 0.003;
var pos = new SuperMap.LonLat(new Number(info.data.X)+xOff,new Number(info.data.Y)+yOff);
infowin = new SuperMap.Popup("chicken",
pos,
new SuperMap.Size(0, 0),
dom,
false, null);
//根据弹窗内容自动调整弹窗大小
infowin.autoSize=true;
//设置默认样式不显示
infowin.setBackgroundColor("none");
map.addPopup(infowin);
highlightFea = new SuperMap.Feature.Vector(new SuperMap.Geometry.Point(info.data.X,info.data.Y),
null,
{
//绘制矢量点方式
// pointRadius:7,
// fillColor:"#3399FF",
// fillOpacity:0.5,
// strokeColor:"#0033FF",
// strokeWidth:3,
// strokeOpacity:0.2
//引用图片方式
externalGraphic:"image/h12.png",
graphicWidth:15,
graphicHeight:15
}
);
vectorLayer.addFeatures([highlightFea]);
}
}
}
};
弹窗展示:利用Control.UTFGrid监听click事件的方式,并结合Popup展示地物的信息,这里的Popup为自定义的CSS样式,因为Popup本身为div,可以任意设计CSS样式。实现效果如下:
//点击弹窗回调函数
var callback2=function(infoLookup1)
{
if(infowin1)
map.removePopup(infowin1);
if(popfeature)
vectorLayer.removeFeatures(popfeature);
if (infoLookup1) {
if (infoLookup1) {
var info1;
for (var idx1 in infoLookup1) {
info1 = infoLookup1[idx1];
if (info1 && info1.data) {
var dom1 = "<div class=‘pop‘ >" +
"<div class=‘pop_header‘><div class=‘pop_close‘ onclick=‘closeInfoWin1()‘></div></div>" +
"<img src=‘image/park.png‘ style=‘height: auto;width: auto;max-width: 100%;opacity: 1‘>" +
"<div class=‘pop_content‘><p><span>地点:</span><span>" + info1.data.name + "</span></p><p><span>坐标:</span><span>x:" + info1.data.X + " y:" + info1.data.Y + "</span></p></div>" +
"<div class=‘pop_arrow‘></div>" +
"</div>";
var xOff1 = -(1 / map.getScale()) * 0.018;
var yOff1 = (1 / map.getScale()) * 0.035;
var pos1 = new SuperMap.LonLat(new Number(info1.data.X) + xOff1, new Number(info1.data.Y) + yOff1);
infowin1 = new SuperMap.Popup("chicken",
pos1,
new SuperMap.Size(20, 20),
dom1,
false, null);
//根据弹窗内容自动调整弹窗大小
infowin1.autoSize = true;
//设置默认样式不显示
infowin1.backgroundColor = "none";
//移动地图以确保弹窗显示在窗口内
infowin1.panMapIfOutOfView=true;
map.addPopup(infowin1);
popfeature = new SuperMap.Feature.Vector(new SuperMap.Geometry.Point(info1.data.X, info1.data.Y),
null,
{
externalGraphic: "image/radar.gif",
graphicWidth: 64,
graphicHeight: 64
}
);
vectorLayer.addFeatures([popfeature]);
}
}
}
}
};
源码地址http://download.csdn.net/detail/supermapsupport/9503675