一、引言
目前在客戶端繪制POI(Point of Interest,興趣點)的方式主要是div(Marker的形式)、svg、canvas、VML(后邊三種就是Vector Layer)幾種方式,這幾種方式中只有canvas的效率是最高的,但是canvas只有一些最新的瀏覽器才支持。雖然div、svg、VML跨瀏覽器要好一些,但是這幾種的效率不夠高,最多只能繪制幾千個POI。
為了展現出大數據量的POI,我們也可以考慮將POI數據集通過iServer發布為臨時圖層,然后在客戶端使用動態圖層展現出來,這樣解決了數據量大和跨瀏覽器的問題,但是這些POI沒法響應鼠標事件。
於是麻點圖應運而生。
二、簡介
SuperMap iClient for JavaScript 提供了麻點圖功能,這是一種很高效的web端大數據量渲染解決方案。該功能支持大數據量、跨瀏覽器、事件響應,並且效率高。 在大部分主流瀏覽器下都能快速渲染,且輕松漫游地圖。

該功能實際上是先調用SuperMap.REST.GetLayersInfoService獲取到服務端圖層信息,然后修改圖層信息,使用SuperMap.REST.SetLayersInfoService設置圖層信息創建臨時圖層,再使用SuperMap.Layer.TiledDynamicRESTLayer將該臨時圖層在客戶端渲染出來。到這一步,大數據量的點就通過瓦片圖片的方式在客戶端渲染出來了。
然后我們再創建SuperMap.Layer.UTFGrid對象,來讓這些POI有鼠標事件響應。然后在最上層疊加一個SuperMap.Layer.Markers,當鼠標移動到某個POI上時,就會在相應位置添加一個Marker,高亮該點。
三、性能

以上報告為服務端存在臨時圖層緩存的情況下,渲染POI點所用的時間,當初次使用麻點圖功能時渲染會比較慢(大數據量下服務端動態切圖是一個比較耗時的操作),初次使用之后(服務端已經存在緩存)渲染POI就要快很多了。
四、使用說明
下面我們來詳細介紹一下如何使用麻點圖。
首先創建一個麻點圖對象。
var url = "http://localhost:8090/iserver/services/map-china400/rest/maps/China";
var myGOIs = new SuperMap.GOIs({
"url":url,
"datasetName":"China_Town_P@China400",
"style":new SuperMap.REST.ServerStyle({
"markerSymbolID":907941,
"markerSize":8
}),
"pixcell": 16
});
以上代碼片段中創建麻點圖需要傳入一些參數:url為所使用的地圖服務的url(通常和TiledDynamicRESTLayer使用的url相同),datasetName為數據對應的子圖層名稱, style為要素的樣式風格,這里需要傳入SuperMap.REST.ServerStyle類型的對象。
然后給麻點圖對象綁定 initialized 事件,麻點圖初始化完成后會觸發該事件。
myGOIs.events.on({
"initialized":GOIsInitialized
});
function GOIsInitialized(){
//獲取麻點圖內部創建的圖層對象,並添加到map上
var layers = myGOIs.getLayers();
map.addLayers(layers);
//創建麻點圖事件控件,該控件用於實現麻點圖的事件響應。
control = new SuperMap.Control.GOIs(layers,{
onClick:function(evt){ //定義click事件
//code
},
highlightIcon:new SuperMap.Icon('images/circle.png', new SuperMap.Size(16,16), new SuperMap.Pixel(-8, -8)),//高亮狀態下的點樣式
isHighlight:true
});
map.addControl(control); //將控件添加到map上
}
這里給麻點圖綁定初始化完成事件,初始化完成后需要完成如下步驟:
- 獲取麻點圖內部創建的圖層對象,並添加到map上,這里你會得到三個圖層對象, 它們分別是:臨時圖層(TiledDynamicRESTLayer)、utfgrid圖層、marker圖層(用於實現高亮效果)。
- 創建麻點圖事件控件,該控件用於實現麻點圖的事件響應,將該控件添加到map上。
用戶需要自己制作一張要素高亮風格的圖片,並將該圖片設置到控件的highlightIcon屬性中
highlightIcon:new SuperMap.Icon('images/circle.png', new SuperMap.Size(16,16), new SuperMap.Pixel(-8, -8)),//高亮狀態下的點樣式
用戶可以通過SuperMap.Control.GOIs給麻點圖添加鼠標事件
可以通過初始化該控件時,以傳參數的方式定義事件。
var control = new SuperMap.Control.GOIs(layers,{
onClick:function(evt){ //定義click事件
//code
}
});
也可以通過事件綁定的方式,給麻點圖定義事件。
control.events.on("mouseover",function(){
//code
});
麻點圖提供了豐富的鼠標事件類型:
- onMouseover
- onMouseout
- onMousemove
- onMousedown
- onMouseup
- onClick
- onDblclick
以下是完整的范例代碼:
<!DOCTYPE>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>麻點圖</title>
<style type="text/css">
body{
margin: 0;
overflow: hidden;
background: #fff;
}
#map{
position: relative;
height: 520px;
border:1px solid #3473b7;
}
#toolbar{
position: relative;
height: 33px;
padding-top:5;
}
</style>
<script src='../libs/SuperMap.Include.js'></script>
<script type="text/javascript">
var map,datasetName,popup,myGOIs,control,
host = document.location.toString().match(/file:\/\//)?"http://localhost:8090":'http://' + document.location.host,
url=host+"/iserver/services/map-china400/rest/maps/China";
function init(){
map = new SuperMap.Map("map",{controls: [
new SuperMap.Control.LayerSwitcher(),
new SuperMap.Control.ScaleLine(),
new SuperMap.Control.Zoom(),
new SuperMap.Control.Navigation({
dragPanOptions: {
enableKinetic: true
}
})],allOverlays: true,projection: "EPSG:3857"
});
layer = new SuperMap.Layer.TiledDynamicRESTLayer("china", url, {transparent: true, cacheEnabled: true}, {maxResolution:"auto"});
layer.events.on({"layerInitialized":addLayer});
}
function addLayer() {
map.addLayers([layer]);
map.setCenter(new SuperMap.LonLat(11782422.179601, 4717749.8315665), 3);
}
function createLayer(){
datasetName = "China_Town_P@China400";
//創建一個麻點圖對象
myGOIs = new SuperMap.GOIs({
"url":url,
"datasetName":datasetName,
"style":new SuperMap.REST.ServerStyle({
"markerSymbolID":907942,
"markerSize":4
}),
"pixcell": 16
});
myGOIs.events.on({
"initialized":GOIsInitialized
});
}
function clearLayer(){
closeInfoWin();
var layers = myGOIs.getLayers();
for(var i=0;i<layers.length;i++){
map.removeLayer(layers[i]);
}
myGOIs.destroy();
myGOIs = null;
control.destroy();
control = null;
}
function GOIsInitialized(){
var layers = myGOIs.getLayers();
map.addLayers(layers);
control = new SuperMap.Control.GOIs(layers,{
onClick:function(evt){
var lonlat = evt.loc;
var name = evt.data.NAME;
openInfoWin(lonlat,name);
},
highlightIcon:new SuperMap.Icon('images/circle.png', new SuperMap.Size(16,16), new SuperMap.Pixel(-8, -8)),
isHighlight:true
});
map.addControl(control);
}
function openInfoWin(lonlat,name){
closeInfoWin();
var contentHTML = "<div style=\'font-size:.8em; opacity: 0.8; overflow-y:hidden;\'>";
contentHTML += "<div>"+name+"</div></div>";
popup = new SuperMap.Popup.FramedCloud("popwin",new SuperMap.LonLat(lonlat.lon,lonlat.lat),null,contentHTML,null,true,function(){
closeInfoWin();
control.removeClickedMarker();
});
map.addPopup(popup);
}
function closeInfoWin() {
if (popup) {
try {
map.removePopup(popup);
}
catch (e) {
}
}
}
</script>
</head>
<body onload="init()">
<div id="toolbar">
<input type="button" value="渲染麻點圖" onclick="createLayer()" />
<input type="button" value="清除" onclick="clearLayer()" />
</div>
<div id="map"></div>
</body>
</html>

這樣我們就可以使用麻點圖功能了,完整范例請見http://www.supermap.com.cn:8090/iserver/iClient/forJavaScript/examples/gois.html
