百度Map與HT for Web結合的GIS網路拓撲應用

來源:互聯網
上載者:User

標籤:style   blog   http   io   ar   color   os   使用   sp   

在《HT for Web整合OpenLayers實現GIS地圖應用》篇中介紹了HT for Web與OpenLayers的整合,不少朋友反應國內用得比較多的還是百度地圖,雖然HT整合百度地圖原理與OpenLayers一致,但不同GIS引擎用戶端結合代碼細節還是有不少差異,自訂地圖風格更是完全不一樣,為此我再開篇介紹下HT與百度地圖整合的方案,這次我們將改進以前的例子,除了代表城市的拓撲節點外,再增加連線串連省會和城市,實現網路拓撲鏈路的流動效果。

百度地圖有多種用戶端SDK,我們這裡用的自然是JavaScript版的API,百度地圖的2.0版增加了不少新功能,例如可以自訂地圖樣式模板,本例中我們特意設定成style:’midnight’的深色背景風格。插入map的位置與OpenLayers也不一樣,通過mapDiv.firstChild.firstChild.appendChild(view);插入,zIndex這些屬性都還好不需要設定。

座標轉換方面從經緯度轉換成平面座標是map.pointToPixel函數,通過node.setPosition(map.pointToPixel(new BMap.Point(lon, lat)));可設定ht.Node對應的平面邏輯座標,通過map.pixelToPoint(new BMap.Pixel(x,y))可將平面座標轉換成經緯度座標,我們在監聽節點圖元被拖拽結束的endMove需要重新計算當前位置的經緯度時用到。

地圖資料方面每個省的省會城市都是第一個出現,因此我們構建了size大一點的帶漸進色的圖元代表省會城市,其他城市構建時同時構建ht.Edge的連線與省會節點串連,同時引入HT的ht-flow.js外掛程式,只需要graphView.enableFlow(60);一句話就可以啟動流動連線功能,每條edge連線還可以有很多flow.*相關的流動參考可控制流程動效果,這裡的簡單例子我們不需要做定製,保持HT預設的流動參數就足夠酷了。

另外通過graphView.setLayers([‘edgeLayer‘, ‘nodeLayer‘]);我們為拓撲設定了兩個層,node.setLayer(‘nodeLayer’);和edge.setLayer(‘edgeLayer’)使得圖元節點全部呈現於連線之上,這個僅是簡單例子如果需要可以隨意定義更多的layers,layers的數組順序決定了最終圖元顯示的先後順序。

傳統使用GIS應用來說圖層都需要操作GIS用戶端API來進行,但從這個例子大家可以發現,以前需要在GIS的SDK擴充的功能也可以通過在HT的GraphView實現,這樣地圖僅僅是作為背景,商務邏輯代碼完全在更靈活強大的HT模型中進行,例元的隱藏和顯示也都在HT的GraphView中重載了graphView.isVisible函數實現的,通過HT設定可以定義到更細節的isNoteVisible這樣的圖元組件是否可見,這裡代碼和OpenLayers有的區別的僅僅是從map.zoom改為map.getZoom()。

另外因為城市節點較多,每次移動介面時我們都需要調用node.setPosition(map.pointToPixel(new BMap.Point(lon, lat)));重新置放圖元平面座標,畢竟對於js來說密集型的大量計算不是其強項,因此我們監聽了map的movestart、moveend、zoomstart、zoomend、dragstart和dragend等事件,做的都是同樣的事情在開始變化前通過view.style.opacity = 0;因此GraphView拓撲圖,當事件結束後通過view.style.opacity = 1;再次顯示拓撲圖,同時調用resetPosition();重新置放圖元節點,這樣保證使用者能夠流暢的操作地圖,而密集型的運算僅在最後才進行一次。

拓撲圖方面還有些細節,例如graphView.setAutoScrollZone(-1)關閉預設拖拽圖元到邊緣時的自動滾動功能,graphView.handleScroll = function(){};關閉拓撲的滾輪縮放功能,graphView.handlePinch = function(){};關閉拓撲在touch觸屏的縮放功能,因為這些功能都要傳遞給Map交給地圖控制。

graphView.mi監聽了moveEnd事件,這個用於某些情況下,使用者需要手工移動節點,意味著要改變節點的經緯度資訊,因此在監聽到moveEnd之後,我們通過data.lonLat = map.pixelToPoint(new BMap.Pixel(x,y));根據螢幕座標重新得到移動後的經緯度資訊。

畢竟GraphView和Map的互動方式是完全不一樣的,因此handleClick在使用者點擊介面時我們需要控制分流,也就是決定此次點擊要交給GraphView處理,還是Map處理,我們通過var data = graphView.getDataAt(e);判斷當前是否點擊中了圖元,如果選中了圖元則GraphView拓撲圖接管互動任務,因此通過e.stopPropagation();停止事件的繼續傳播,如果點擊在背景上則無需特殊處理,Map自動會接管任務,畢竟我們是通過mapDiv.firstChild.firstChild.appendChild(view);的方式插入拓撲圖,mapDiv作為底層父輩類組件依然會監聽到事件,這點比OpenLayers的整合容易很多,沒有太多需要特殊設定的地方。

構建城市節點依然採用了http://llllll.li/randomColor/隨機產生顏色的架構,僅對省會節點增加了漸進色的效果,省會節點和城市節點間構建了ht.Edge連線,通過‘flow‘: true的style啟動連線流動,flow.*還有很多控制參數,例如控制流程動的方向,流動的效果等,這裡就不再展開介紹了。

以下為操作視頻、抓圖和原始碼供大家參考,這樣的結合可完美的將百度地圖豐富的地圖資料資訊,與HT強大的邏輯拓撲功能相結合,否則光靠百度地圖SDK的API的擴充方式,使用者只能做些簡單的效果,例如連線流動等效果都遠不如HT這樣一行代碼就搞定來的容易。http://v.youku.com/v_show/id_XODQxMDcwNjQ0.html


 

var dataModel = new ht.DataModel();var graphView = new ht.graph.GraphView(dataModel);              var map = null;   function init() {    map = new BMap.Map("map");       var point = new BMap.Point(116.404, 39.915);                              map.addTileLayer(new BMap.TrafficLayer());                        map.centerAndZoom(point, 4);                        map.enableScrollWheelZoom();                           map.addControl(new BMap.NavigationControl());                                   map.setMapStyle({        features: ["road", "building","water","land"],        style:‘midnight‘    });    var view = graphView.getView();    view.className = ‘graphView‘;     var mapDiv = document.getElementById(‘map‘);    mapDiv.firstChild.firstChild.appendChild(view);    map.addEventListener(‘movestart‘, function(e){                          view.style.opacity = 0;    });    map.addEventListener(‘moveend‘, function(e){       view.style.opacity = 1;        resetPosition();     });    map.addEventListener(‘dragstart‘, function(e){       view.style.opacity = 0;                    });    map.addEventListener(‘dragend‘, function(e){       view.style.opacity = 1;        resetPosition();     });                                    map.addEventListener(‘zoomstart‘, function(e){        view.style.opacity = 0;    });                    map.addEventListener(‘zoomend‘, function(e){        view.style.opacity = 1;            resetPosition();     });                    graphView.setLayers([‘edgeLayer‘, ‘nodeLayer‘]);    graphView.enableFlow(60);    graphView.enableToolTip();    graphView.getToolTip = function(event){        var data = this.getDataAt(event);        if(data instanceof ht.Node){            return ‘城市:‘ + data.s(‘note‘) + ‘經度:‘ + data.lonLat.lng + ‘維度:‘ + data.lonLat.lat;        }        return null;    };    graphView.isVisible = function(data){        return map.getZoom() > 1 || this.isSelected(data);    };    graphView.isNoteVisible = function(data){        return map.getZoom() > 8 || this.isSelected(data);    };     graphView.getLabel = function(data){        if(data instanceof ht.Node){            return ‘經度:‘ + data.lonLat.lng + ‘\n維度:‘ + data.lonLat.lat;        }                        };    graphView.isLabelVisible = function(data){        return map.getZoom() > 9 || this.isSelected(data);    };     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.pixelToPoint(new BMap.Pixel(x,y));                 }                                        });        }    });    graphView.setAutoScrollZone(-1);    graphView.handleScroll = function(){};    graphView.handlePinch = function(){};    var handleClick = function(e){        var data = graphView.getDataAt(e);        if(data){            e.stopPropagation();        }        else if(e.metaKey || e.ctrlKey){            e.stopPropagation();        }    };    graphView.getView().addEventListener(‘click‘, handleClick, false);                    graphView.getView().addEventListener(‘dblclick‘, handleClick, false);    graphView.getView().addEventListener(ht.Default.isTouchable ? ‘touchstart‘ : ‘mousedown‘, handleClick, false);    window.addEventListener("resize", function(e) {        graphView.invalidate();    }, false);                     var color = randomColor(),        province = null;    lines = china.split(‘\n‘);    for(var i=0; i<lines.length; i++) {        line = lines[i].trim();        if(line.indexOf(‘【‘) === 0){                           color = randomColor();            province = null;        }else{            var ss = line.split(‘ ‘);            if(ss.length === 3){                var node = createNode(parseFloat(ss[1].substr(3)), parseFloat(ss[2].substr(3)), ss[0].substr(3), color);                 if(province){                    var edge = new ht.Edge(province, node);                    edge.s({                        ‘edge.center‘: true,                        ‘edge.width‘: 1,                                                            ‘flow‘: true                    });                    edge.setLayer(‘edgeLayer‘);                    dataModel.add(edge);                }else{                    province = node;                    node.s({                                                           ‘shape.gradient‘: ‘radial.center‘,                                                            ‘border.type‘: ‘circle‘,                        ‘border.width‘: 1,                        ‘border.color‘: ‘rgba(200, 200, 200, 0.5)‘                                                        });                    node.setSize(15, 15);                }            }        }    }                }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.setLayer(‘nodeLayer‘);    node.setSize(10, 10);    var lonLat = new BMap.Point(lon, lat);     node.setPosition(map.pointToPixel(lonLat));    node.lonLat = lonLat;    graphView.dm().add(node);    return node;}            function resetPosition(e){    graphView.tx(0);    graphView.ty(0);    dataModel.each(function(data){        if(data instanceof ht.Node){            var lonLat = data.lonLat,                position = map.pointToPixel(lonLat);               data.setPosition(position.x,position.y);                                   }    });            }

 

百度Map與HT for Web結合的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.