HT for Web整合OpenLayers實現GIS地圖應用

來源:互聯網
上載者:User

標籤:style   blog   http   io   ar   color   os   sp   for   

HT for Web作為邏輯拓撲圖形組件自身沒有GIS功能,但可以與各種GIS引擎即其用戶端組件進行融合,各取所長實現邏輯拓撲和物理拓撲的無縫融合,本章將具體介紹HT for Web與開發免費的OpenLayers地圖結合應用的關鍵技術點,該文介紹的結合的原理,其實還可推廣到與ArcGIS、百度地圖以及GoogleMap等眾多GIS地圖引擎融合的解決方案。

以上抓圖為本文介紹的例子最終運行效果,接下來我們一步步來實現,首選顯示地圖資訊需要有城市經緯度資料,搜尋了下感謝此篇部落格提供的資料。這麼大量的資料我採用的是《HT圖形組件設計之道(四)》中介紹的getRawText函數方式,有了資料之後剩下就是呈現的問題了,我們需要將HT的GraphView組件與OpenLayers的map地圖組件疊加在一起,也就是OpenLayers的tile地圖圖片在下方,GraphView的組件在上方,由於GraphView預設是透明的,因此非圖元部分使用者可穿透看到地圖內容。找到合適的組件插入位置是頭疼的事情,ArcGIS、百度地圖包括GoogleMap幾乎每個不同的GIS組件都需要嘗試一番才能找到合適的插入位置,其他GIS引擎組件的整合以後章節再介紹,本文我們關注的OpenLayers的插入方式為map.viewPortDiv.appendChild(graphView.getView())。

HT和OpenLayers組件疊加在一起之後,剩下就是拓撲裡面圖元的擺放位置與經緯度結合的問題,常規網路拓撲圖中儲存在ht.Node圖元的position是邏輯位置,和經緯度沒有任何關係,因此在GIS應用中我們需要根據圖元的經緯度資訊換算出position的螢幕邏輯座標資訊,如果你知道投影演算法也可以自己提供函數處理,但所有GIS組件都提供了類似的API函數供調用,當然這部分也沒有標準化,不同的GIS組件需要調用的API都有差異,但基本原理是一致的,對於OpenLayers我們通過map.getPixelFromLonLat(data.lonLat)可以將經緯度資訊轉換成螢幕像素邏輯座標,也就是ht.Node需要的position座標資訊。

細心的同學會想到轉換是雙向的,有可能使用者需要拖動圖元節點改變其經緯度資訊,這時候我們就需要另外一個方向函數,即根據螢幕邏輯座標轉換成當前座標組應的經緯度,在OpenLayers中我們通過map.getLonLatFromPixel(new OpenLayers.Pixel(x, y));可以搞定。

顯示搞定後剩下就是互動的問題了,HT自己有套互動體系,OpenLayers也需要地圖漫遊和縮放的互動,兩者如何結合呢?如果能保留住兩者的功能那就最好了,答案時肯定的,我們只需要添加mousedown或touchstart事件監聽,如果graphView.getDataAt(e)選中了圖元我們就通過e.stopPropagation();停止事件的傳播,這樣map地圖就不會響應,這時候HT接管了互動,如果沒有選中圖元則map接管地圖操作的互動。

以上互動設計似乎很完美了,結果運行時發現了幾處折騰了我很久才找到解決方案的坑:

  1. 設定map.events.fallThrough = true;否則map不會將事件透傳到HT的GraphView組件

  2. graphView.getView().style.zIndex = 999; 需要指定一定的zIndex否則會被遮擋

  3. graphView.getView().className = ‘olScrollable’; 否則滾輪不會響應地圖縮放

  4. 設定ht.Default.baseZIndex: 1000 否則ToolTip會被遮擋

為了讓這個例子使用者體驗更友好,我還用心折騰了些技術點供參考:

  1. 採用開源免費的http://llllll.li/randomColor/隨機顏色類庫,該類庫還有很多非常棒的顏色擷取函數,我只是簡單的為每個省份顯示不一樣的顏色

  2. 重載了isVisible、isNoteVisible和isLabelVisible僅在縮放達到一定層級才顯示更詳細的內容,否則縮小時所有城市資訊都顯示完全無法查看,多少也能提高顯示效能

以下為最終效果的抓圖、視頻和原始碼:http://v.youku.com/v_show/id_XODM5Njk0NTU2.html

   

function init(){                graphView = new ht.graph.GraphView();var view = graphView.getView();                 map = new OpenLayers.Map("map");var ol_wms = new OpenLayers.Layer.WMS("OpenLayers WMS","http://vmap0.tiles.osgeo.org/wms/vmap0",{layers: "basic"});map.addLayers([ol_wms]);map.addControl(new OpenLayers.Control.LayerSwitcher());map.zoomToMaxExtent();                map.events.fallThrough = true;map.zoomToProxy = map.zoomTo;map.zoomTo =  function (zoom,xy){view.style.opacity = 0;map.zoomToProxy(zoom, xy);    console.log(zoom);};                map.events.register("movestart", this, function() {});map.events.register("move", this, function() {                   });map.events.register("moveend", this, function() {view.style.opacity = 1;reset();});                graphView.getView().className = ‘olScrollable‘;graphView.setScrollBarVisible(false);graphView.setAutoScrollZone(-1);graphView.handleScroll = function(){};graphView.handlePinch = function(){};     graphView.mi(function(e){if(e.kind === ‘endMove‘){graphView.sm().each(function(data){if(data instanceof ht.Node){   var position = data.getPosition(),   x = position.x + graphView.tx(),   y = position.y + graphView.ty();     data.lonLat = map.getLonLatFromPixel(new OpenLayers.Pixel(x, y));                                                                     }                            });}});graphView.enableToolTip();graphView.getToolTip = function(event){var data = this.getDataAt(event);if(data){return ‘城市:‘ + data.s(‘note‘) + ‘經度:‘ + data.lonLat.lon + ‘維度:‘ + data.lonLat.lat;}return null;};graphView.isVisible = function(data){return map.zoom > 1 || this.isSelected(data);};graphView.isNoteVisible = function(data){return map.zoom > 6 || this.isSelected(data);}; graphView.getLabel = function(data){return ‘經度:‘ + data.lonLat.lon + ‘\n維度:‘ + data.lonLat.lat;};graphView.isLabelVisible = function(data){return map.zoom > 7 || this.isSelected(data);};                 view.addEventListener("ontouchend" in document ? ‘touchstart‘ : ‘mousedown‘, function(e){var data = graphView.getDataAt(e);if(data || e.metaKey || e.ctrlKey){e.stopPropagation();}                      }, false); view.style.position = ‘absolute‘;view.style.top = ‘0‘;view.style.left = ‘0‘;view.style.right = ‘0‘;view.style.bottom = ‘0‘;                view.style.zIndex = 999;map.viewPortDiv.appendChild(view);var color = randomColor();lines = china.split(‘\n‘);for(var i=0; i<lines.length; i++) {line = lines[i].trim();if(line.indexOf(‘【‘) === 0){//province = line.substring(1, line.length-1);                color = randomColor();}else{var ss = line.split(‘ ‘);if(ss.length === 3){createNode(parseFloat(ss[1].substr(3)), parseFloat(ss[2].substr(3)), ss[0].substr(3), color);                                                      }}}                                }function reset(){graphView.tx(0);graphView.ty(0);graphView.dm().each(function(data){                    if(data.lonLat){                            data.setPosition(map.getPixelFromLonLat(data.lonLat));                           }});graphView.validate();}function createNode(lon, lat, name, color){var node = new ht.Node();node.s({‘shape‘: ‘circle‘,‘shape.background‘: color,‘note‘: name,                    ‘label.background‘: ‘rgba(255, 255, 0, 0.5)‘,                    ‘select.type‘: ‘circle‘});node.setSize(10, 10);var lonLat = new OpenLayers.LonLat(lon, lat);lonLat.transform(‘EPSG:4326‘, map.getProjectionObject());node.setPosition(map.getPixelFromLonLat(lonLat));node.lonLat = lonLat;graphView.dm().add(node);return node;}


HT for Web整合OpenLayers實現GIS地圖應用

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.