淺談Supermap iClient for JavaScript 彈窗類


  地圖作為信息的載體和呈現方式,是GIS的重要組成部分,它是一個瀏覽信息的窗口,在信息日益發達的今天 ,各種地圖應用如雨后春筍一般出現在大眾眼前,而不是像以往一樣太過局限於專業的領域。而彈窗,是作為地圖信息的補充說明和描述的重要呈現方式,也廣泛應用於各種地圖應用中。一個好的前端界面的設計要靈活地使用空間,也要生動地完成與用戶的交互,而在地圖應用中,彈窗使用得好,不但會讓人感覺舒適也會方便和增加與用戶的交互,提升用戶體驗。如何使用和如何更好地使用iClient for JavaScript的彈窗(Popup)類,便是本文要探討的話題。

lalala

一、 基礎

1. 分類

       普通彈窗SuperMap.Popup):同時也是彈窗類的基類,不僅可以直接new出來,還能被子類繼承其公開的屬性和方法,JS API手冊列舉的屬性和方法均可被其子類繼承。其默認出現位置是,彈窗左上角在給定坐標點。

其默認效果如下↓:

普通彈窗


       固定錨點位置彈窗SuperMap.Popup.Anchored):固定錨點位置的的浮動彈窗,可以圍繞指定位置四周自適應顯示。即當彈窗定位點(lonlat)在當前地圖可視范圍邊緣時,會自動調整彈窗哪個角停靠在定位點。

其默認效果如下↓:

固定錨點位置彈窗


       帶小尾巴的彈窗SuperMap.Popup.FramedCloud):具有指向和邊框的浮動彈窗。它雖然沒有邊緣自適應位置的效果,但具有邊緣時移動地圖使彈窗顯示完整的效果和陰影效果。

其默認效果如下↓:

指向彈窗


2. 使用

彈窗類的使用很簡單,new一個加到地圖里就好了,這里以FramedCloud為例,上代碼

 1 var map = new SuperMap.Map("map");                //引號內map為頁面div元素ID
 2 
 3 //初始化FramedCloud類
 4 var framedCloud = new SuperMap.Popup.FramedCloud(
 5     "chicken",                              //彈窗的唯一標識ID,即加載在地圖上的彈窗div的ID
 6    new SuperMap.LonLat(11339634, 4588716), //當前地圖上的坐標點,用於定位彈窗位置
 7    new SuperMap.Size(120,60),             //彈窗內容的大小,可以為null
 8    '<div style="margin:25px 10px; padding:0;"> 彈窗內容,相當於div元素的innerHTML
 9 </div>',
10    null,                                //錨點,即彈窗怎么定位到坐標點
11    true,                               //bool,是否顯示關閉按鈕
12    null,                              //Function,關閉彈窗觸發該回調函數
13    false                             //是否顯示陰影,默認為true
14 );
15 framedCloud.fixedRelativePosition=true;        // 是否固定相對位置,默認為false。
16 var layer = new SuperMap.Layer.CloudLayer();  //初始化超圖雲圖層
17 map.addLayers([layer]);                      //添加超圖雲圖層
18 map.setCenter(new SuperMap.LonLat(11339634, 4588716), 4); //設置顯示的中心點及比例尺級別
19 map.addPopup(framedCloud);                 //將彈窗加載到map控件上,即放在地圖上
 就這樣?就這樣。 

       JS API類參考里有更多的屬性和方法,可以自己去調整、設置。上面的代碼只是初始化時就給放個彈窗,顯然不符合我們的需要,但是已經足夠說明它的用法了。彈窗基礎的用法就是這么用,彈窗內容的部分,你可以自由發揮了,可以使用第三方插件,JQuery UI教程)、BootStrap等等,你可以自由定制彈窗的內容。

       一般我們怎么用?最常見的就是點擊地圖上的圖標,任何可以注冊點擊事件的地方來添加彈窗。下面舉個例子:

       點擊點對象,顯示彈窗: 
       這里使用SuperMap.Layer.Vector圖層上的點對象(其他對象也一樣),點對象怎么得到,怎么風格化處理就不多說了,我們來看看它需要什么參數: 
       首先,最重要的參數,定位點,它是SuperMap.LonLat類型的,所以我們得想辦法得到所點擊的點的坐標。SuperMap.Layer.Vector圖層上要素的點擊事件可以用SuperMap.Control.SelectFeature來注冊,設置onSelect屬性並且設置其repeat屬性為true,或者使用callbacks屬性(JS API類參考可以看到支持的事件)來實現點擊事件:

1 var selectFeature = new SuperMap.Control.SelectFeature(VectorLayer,{onSelect:onFeatureSelect,repeat:true,selectStyle:style});
2 //onSelect:{Function},當要素被選中時調用該方法,要求用戶定義具體方法,該方法接收當前選中要素作為參數。
3 //function onFeatureSelect(e){}; 

順便說下,設置VectorLayer要素選中狀態樣式的方法有很多,上面就是其中之一。 

我們來看看點擊(這里是重復觸發的選中事件)事件觸發后,傳給回調函數的參數里有沒有我們想要的坐標參數,用console.log(e)看看:

console


       雖然沒有直接的lonlat對象,但好在有geometry對象,它就是這個點對象的信息,可是類參考里,SuperMap.Geometry.Point點對象沒有直接獲取lonlat對象的方法和屬性,一種方法是new一個SuperMap.LonLat對象,我這里使用另外一種Geometry對象通用的方法,先用geometry.getBounds()方法獲取Geometry對象的Bounds,再使用SuperMap.Bounds對象的Bounds.getCenterLonLat()方法獲取其中心坐標點lonlat對象:

1 var lonlat= e.geometry.getBounds().getCenterLonLat();

       有了定位點,接下來要怎么做就不用我多說了吧?這里再補充一下錨點屬性的使用,它是用來定位彈窗相對於定位點位置用的,一般使用SuperMap.Icon對象,它不會在彈窗任何位置添加一個圖標,使用它是因為不需要再構造一個包含大小信息和偏移量信息的對象,使用它可以使你的彈窗停靠在點圖標圖片的上方而不至於讓小尾巴與圖標重疊,效果對比如下↓:


錨點


       有了上面的例子,那么其他Geometry對象就都ok了,只要參數給對了就行。 
       另外,有的朋友不想使用客戶端圖層再彈窗,那怎么辦呢?iServer 7C開始支持屬性瓦片,同時客戶端也有相關對接的類,即:SuperMap.Layer.UTFGrid。JS API有這兩個圖層使用的相關示例,這里稍稍提示下:

       UTFGrid使用SuperMap.Control.UTFGrid控件注冊事件,支持的事件類型有點擊(click)、懸停(hover)和拖拽(move)。

       再補充個,為處理海量數據而生的麻點圖,使用SuperMap.Control.GOIs控件注冊其事件。

3.其他

  • 視具體彈窗類型不同,其構造函數的參數數量有所不同,FramedCloud的構造函數已包含了別的類型彈窗的所有參數,所以其余彈窗類型不再贅述。
  • 了解一下它們的繼承關系,子類繼承父類的屬性和方法。

二、 進階

       類參考里的方法和屬性及其組合不能做到你想要做的效果?總之就是想做通過iClient for JavaScript做不到的彈窗效果?看這里就對了,之所以是進階而不是高級,是因為我下面要說的其實很簡單,也不需要去對JS API的源碼進行修改、重寫和擴展。好了我就不賣關子了,一句話就可以說清楚:

       添加到地圖上的彈窗是div。

       好了,我說完了,下課。 
       就這樣?就這樣!早該想到的是不是?這句話說完其實就已經很好的總結了接下來的內容了,那么接下來就簡單的介紹下,然后小伙伴們就可以愉快地玩耍、盡情地發揮想象力了。

1. 彈窗內邊距、滾動條、邊框、陰影、半透明等等效果和動畫效果

看圖↓:

DIV


       想起什么了嗎?彈窗這個div的ID就是我們new這個彈窗時第一個參數給的,而知道了整個彈窗的div及其嵌套關系后這第一個問題就算解決了是吧?雖然類參考里有部分比如邊框、透明度樣式設置的方法,但根據這個來設置顯然更靈活。 
       另外,通過iClient JS主題包(theme文件夾)中的style.css文件,可以找到部分彈窗類樣式的定義:

1 .smFramedCloudPopupContent {
2     padding: 5px;
3     overflow: auto;
4 }

       不建議在原文件修改(實在要改記得備份),你需要的只是定義個CSS樣式覆蓋或追加到默認樣式,為保證覆蓋掉默認樣式,可以在樣式后面加 !important,比如:

1 .smFramedCloudPopupContent{
2    overflow:hidden !important;
3    padding:0 !important;
4 }

       上面的效果就是彈窗內容(你寫的那部分的外層div)不顯示滾動條,內邊距為0。

       當然,你可以在style.css(在\theme\default下)文件中搜索Popup相關的樣式來設置,但是通過瀏覽器查看元素更直觀方便,之所以要去查看下默認樣式的定義是為了避免自定義樣式不生效,現在你知道了,加個!important 覆蓋掉默認的就好了。 
到此,你可以使用各種UI、動畫庫(推薦animate.css)了,可以盡情發揮了。

2. 實現彈窗隨鼠標移動或隨地圖上點移動的思路

       map上加上彈窗后,如何實現移動彈窗?每次位置更改(onlat屬性)先移除彈窗再添加可不可以呢?當然是可以的,如果你不需要和用戶交互也不考慮彈窗多的情況下的性能的話。這是一種方法,但是不用考慮。

       首先,收集必要信息:

       1. 我們已經知道彈窗的ID(new 彈窗時自己給的,也可以在瀏覽器里查看),要用要改變它的位置,只需要設置它樣式的left和top值,怎么獲取呢? 
       2.看看popup對象除了是個div外,有沒有在map對象里

先看看map控件下有什么屬性和方法:


屬性 描述
popups {Array(SuperMap.Popup)} 地圖上的彈窗列表。

方法 描述
getViewPortPxFromLayerPx 根據圖層像素點坐標獲取視圖窗口像素點坐標
getViewPortPxFromLonLat 根據指定地理位置,返回其相對於當前地圖窗口左上角的像素位置
getPixelFromLonLat 獲取地圖上的像素坐標。依照當前baselayer,將指定的地理點位置坐標, 轉換成其相對於地圖窗口左上角點的像素坐標
getLonLatFromPixel 根據相對於地圖窗口左上角的像素位置,返回其在地圖上的地理位置。依據當前baselayer轉換成 lon/lat (經度/緯度)形。
getLayerPxFromLonLat 根據傳入的大地坐標獲取圖層坐標對象
getLayerPxFromViewPortPx 根據視圖窗口像素點坐標獲取圖層像素點坐標
removeAllPopup 移除所有彈出窗口。
removePopup 移除指定的彈出窗口。

       對於第一種思路要求,使用getLonLatFromPixelgetPixelFromLonLat方法就可以實現了,而且不需要計算地圖容器在頁面中的位置,不過這樣改了后,彈窗對象的lonlat等屬性不會變化,需要的話可以手動改下它的屬性;另外,自帶的陰影(多個div拼合而成)也不會跟着移動,也需要手動改,跟上面的方法一樣,或者不使用自帶的陰影,而使用用彈窗DIV的CSS陰影樣式,這里用setInterval簡單模擬了下:

 1 function mouseClickHandler(e){
 2                 closeInfoWin();
 3 
 4                 var framedCloud= new SuperMap.Popup.FramedCloud(
 5                     "chicken",
 6                     e.object.lonlat,
 7                     null,
 8                     '這里相當於innerHTML部分',
 9                     new SuperMap.Icon('', new SuperMap.Size(21,25), new SuperMap.Pixel(-10, -20)),
10                     true,
11                     null,
12                     true
13                 );
14                 framedCloud.panMapIfOutOfView=true;
15                 infowin = framedCloud;
16                 map.addPopup(framedCloud);
17                 //在一定范圍內隨機更改彈窗位置
18                 setInterval(function(){
19                     var px=map.getPixelFromLonLat(new SuperMap.LonLat(e.object.lonlat.lon+Math.random()*100000,e.object.lonlat.lat+Math.random()*100000));
20                     document.getElementById("chicken" ).style.left=px.x+"px";
21                     document.getElementById("chicken" ).style.top=document.getElementById("chicken" ).style.height+px.y;
22                 },100);
23             }

       對於第二種思路,當然就是獲取到popup對象,改它的lonlat屬性,但是你會發現改了之后,彈窗並沒有移動,因為你只是改了對象的屬性,div並不受影響,除非刷新地圖或重繪div。但是,還是有辦法的,用SuperMap.Popup.updateSize()方法就可以了:

1 setInterval(function(){
2                     var lonlat=new SuperMap.LonLat(e.object.lonlat.lon+Math.random()*100000,e.object.lonlat.lat+Math.random()*100000);
3                     map.popups[0].lonlat=lonlat;
4                     map.popups[0].updateSize();
5                 },1000);
6             }

       二者可以結合使用,第一種思路更為靈活。瀏覽器里多按f12,這很重要。


       關於彈窗類,進階的內容就到這里了,高級的內容大家就自己探索吧。希望本文能給你一些啟發、開闊一些思路。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM