小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

HT for Web整合OpenLayers實(shí)現(xiàn)GIS地圖應(yīng)用

 看見就非常 2015-09-18
摘要 HT for Web作為邏輯拓?fù)鋱D形組件自身沒有GIS功能,但可以與各種GIS引擎即其客戶端組件進(jìn)行融合,各取所長實(shí)現(xiàn)邏輯拓?fù)浜臀锢硗負(fù)涞臒o縫融合,本章將具體介紹HT for Web與開發(fā)免費(fèi)的OpenLayers地圖結(jié)合應(yīng)用的關(guān)鍵技術(shù)點(diǎn),該文介紹的結(jié)合的原理,其實(shí)還可推廣到與ArcGIS、百度地圖以及GoogleMap等眾多GIS地圖引擎融合的解決方案。

HT for Web作為邏輯拓?fù)鋱D形組件自身沒有GIS功能,但可以與各種GIS引擎即其客戶端組件進(jìn)行融合,各取所長實(shí)現(xiàn)邏輯拓?fù)浜臀锢硗負(fù)涞臒o縫融合,本章將具體介紹HT for Web與開發(fā)免費(fèi)的OpenLayers地圖結(jié)合應(yīng)用的關(guān)鍵技術(shù)點(diǎn),該文介紹的結(jié)合的原理,其實(shí)還可推廣到與ArcGIS、百度地圖以及GoogleMap等眾多GIS地圖引擎融合的解決方案。

Screen Shot 2014-12-02 at 1.15.33 AM

以上抓圖為本文介紹的例子最終運(yùn)行效果,接下來我們一步步來實(shí)現(xiàn),首選顯示地圖信息需要有城市經(jīng)緯度數(shù)據(jù),搜索了下感謝此篇博客提供的數(shù)據(jù)。這么大量的數(shù)據(jù)我采用的是《HT圖形組件設(shè)計(jì)之道(四)》中介紹的getRawText函數(shù)方式,有了數(shù)據(jù)之后剩下就是呈現(xiàn)的問題了,我們需要將HT的GraphView組件與OpenLayers的map地圖組件疊加在一起,也就是OpenLayers的tile地圖圖片在下方,GraphView的組件在上方,由于GraphView默認(rèn)是透明的,因此非圖元部分用戶可穿透看到地圖內(nèi)容。找到合適的組件插入位置是頭疼的事情,ArcGIS、百度地圖包括GoogleMap幾乎每個不同的GIS組件都需要嘗試一番才能找到合適的插入位置,其他GIS引擎組件的整合以后章節(jié)再介紹,本文我們關(guān)注的OpenLayers的插入方式為map.viewPortDiv.appendChild(graphView.getView())。

HT和OpenLayers組件疊加在一起之后,剩下就是拓?fù)淅锩鎴D元的擺放位置與經(jīng)緯度結(jié)合的問題,常規(guī)網(wǎng)絡(luò)拓?fù)鋱D中存儲在ht.Node圖元的position是邏輯位置,和經(jīng)緯度沒有任何關(guān)系,因此在GIS應(yīng)用中我們需要根據(jù)圖元的經(jīng)緯度信息換算出position的屏幕邏輯坐標(biāo)信息,如果你知道投影算法也可以自己提供函數(shù)處理,但所有GIS組件都提供了類似的API函數(shù)供調(diào)用,當(dāng)然這部分也沒有標(biāo)準(zhǔn)化,不同的GIS組件需要調(diào)用的API都有差異,但基本原理是一致的,對于OpenLayers我們通過map.getPixelFromLonLat(data.lonLat)可以將經(jīng)緯度信息轉(zhuǎn)換成屏幕像素邏輯坐標(biāo),也就是ht.Node需要的position坐標(biāo)信息。

細(xì)心的同學(xué)會想到轉(zhuǎn)換是雙向的,有可能用戶需要拖動圖元節(jié)點(diǎn)改變其經(jīng)緯度信息,這時候我們就需要另外一個方向函數(shù),即根據(jù)屏幕邏輯坐標(biāo)轉(zhuǎn)換成當(dāng)前坐標(biāo)對應(yīng)的經(jīng)緯度,在OpenLayers中我們通過map.getLonLatFromPixel(new OpenLayers.Pixel(x, y));可以搞定。

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

以上交互設(shè)計(jì)似乎很完美了,結(jié)果運(yùn)行時發(fā)現(xiàn)了幾處折騰了我很久才找到解決方案的坑:

  1. 設(shè)置map.events.fallThrough = true;否則map不會將事件透傳到HT的GraphView組件

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

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

  4. 設(shè)置ht.Default.baseZIndex: 1000 否則ToolTip會被遮擋

為了讓這個例子用戶體驗(yàn)更友好,我還用心折騰了些技術(shù)點(diǎn)供參考:

  1. 采用開源免費(fèi)的http:///randomColor/隨機(jī)顏色類庫,該類庫還有很多非常棒的顏色獲取函數(shù),我只是簡單的為每個省份顯示不一樣的顏色

  2. 重載了isVisible、isNoteVisible和isLabelVisible僅在縮放達(dá)到一定級別才顯示更詳細(xì)的內(nèi)容,否則縮小時所有城市信息都顯示完全無法查看,多少也能提高顯示性能

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

Screen Shot 2014-12-02 at 1.15.33 AM Screen Shot 2014-12-02 at 1.16.18 AM Screen Shot 2014-12-02 at 1.16.47 AM Screen Shot 2014-12-02 at 1.17.30 AM

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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./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"thisfunction() {
    });
    map.events.register("move"thisfunction() {                   
    });
    map.events.register("moveend"thisfunction() {
        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') + '
經(jīng)度:' + 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 '經(jīng)度:' + 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;
}


    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多