帶你剖析WebGis的世界奧秘—-Geojson數據加載(高級)

帶你剖析WebGis的世界奧秘—-Geojson數據加載(高級)

Geojson數據解析

GeoJSON是一種對各種地理數據結構進行編碼的格式。GeoJSON對象可以表示幾何、特征或者特征集合。GeoJSON支持下面幾何類型:點、線、面、多點、多線、多面和幾何集合。GeoJSON裡的特征包含一個幾何對象和其他屬性,特征集合表示一系列特征。

一個完整的GeoJSON數據結構總是一個(JSON術語裡的)對象。在GeoJSON裡,對象由名/值對–也稱作成員的集合組成。對每個成員來說,名字總是字符串。成員的值要麼是字符串、數字、對象、數組,要麼是下面文本常量中的一個:”true”,”false”和”null”。數組是由值是上面所說的元素組成。

GeoJSON集合特征:

{"type":"FeatureCollection",
    "features":[
        {"type":"Feature",
         "id":"001",
         "properties":{"name":"新華001"},
         "geometry":{"type": "Point", "coordinates":[121.9850,42.6737]}},
        {"type":"Feature",
         "id":"002",
         "properties":{"name":"新華002"},
         "geometry":{"type": "Point", "coordinates":[121.8345,42.4898]}},
        {"type":"Feature",
         "id":"003",
         "properties":{"name":"峰山1"},
         "geometry":{"type": "LineString", "coordinates":[[121.9850,42.6737],[121.8345,42.4898]]}},
        {"type":"Feature",
         "id":"004",
         "properties":{"name":"新華1001"},
         "geometry":{"type": "Point", "coordinates":[128.9850,42.6737]}},
        {"type":"Feature",
         "id":"005",
         "properties":{"name":"新華1002"},
         "geometry":{"type": "Point", "coordinates":[125.8345,42.4898]}},
        {"type":"Feature",
         "id":"006",
         "properties":{"name":"峰山2"},
         "geometry":{"type": "LineString", "coordinates":[[121.9850,42.6737],[125.8345,42.4898]]}}]}

openlayers3代碼加載

至於如何加載地圖在第一篇的加載瓦片式地圖已經提過瞭,看完第一篇的你應該知道我是將地圖map交接給頁面的p中,而map中包含瞭很多遮罩層,我現在加載GeoJSON就是在最上面的層上在加載url數據。

var vector = new ol.layer.Vector( {
    source : new ol.source.Vector( {
        // url:
        // 'https://openlayers.org/en/v3.17.1/examples/data/geojson/countries.geojson',
        url : './source/china.json',
        format : new ol.format.GeoJSON()
    }),
    style : selectStyleFunction
});

我這是引用本地準備好的數據(可以從服務器上獲得,從服務器上隻需要將url地址改寫成服務地址),加載url完成後並不會在map中顯示出來,我們還需要指定數據的顯示樣式,這裡和之前瓦片是加載不同,樣式很重要我調節瞭好久才調通的,這裡我將封裝在方法裡。

方法的具體實現:

    var style;
    if(feature.getGeometry().getType()=="Point"){
        style = [new ol.style.Style({
            image : new ol.style.Circle( {
                fill : new ol.style.Fill( {
                    color : 'rgba(255,255,0,0.4)'
                }),
                radius : 2,
                stroke : new ol.style.Stroke( {
                    color : 'black',
                    width : 1
                })
             }),
             text : new ol.style.Text( {
                    fill : textFill,
                    stroke : textStroke,
                    text : view.getZoom()>5?(feature.getId()>2?feature.get("name"):""):""
                })
            })];
    }else if(feature.getGeometry().getType()=="LineString"){
        if(view.getZoom()<3){
            return ;
        }
        style = [new ol.style.Style( {
            stroke : new ol.style.Stroke( {
                color : '#CD950C',
                width : 2
            }),
             text : new ol.style.Text( {
                    fill : textFill,
                    stroke : textStroke,
                    text : view.getZoom()>6?feature.get("name"):""
                })
        })];
    }else if(feature.getGeometry().getType()=="Polygon"){
        style = [new ol.style.Style( {
            stroke : new ol.style.Stroke( {
                color : '#FFE4B5',
                width : 3
            }),
             text : new ol.style.Text( {
                    fill : textFill,
                    stroke : textStroke,
                    text : feature.get("name")
                })
        })];
    }else if(feature.getGeometry().getType()=="MultiLineString"){
        style = [new ol.style.Style( {
            stroke : new ol.style.Stroke( {
                color : 'black',
                width : 3
            })
        })];
    }
    return style;

申明 裡面有些參數沒有進行申明,因為定義瞭全局變量,因為在之前的js中改的,所以並沒貼出所有代碼。這裡需要完整代碼的請CSDN上私信我或者在留言板上留言


效果欣賞

1、地圖加載完畢 這裡你看到的地圖不是上次的瞭,這次這個地圖就是GeoJSON裡的數據,隻不過將數據以圖形化的形式展現在我們的面前,看到地圖右上方的兩個點和一條線瞭嗎,那都是通過數據動態加載出來的,換句話來說就是,我隻需要將GeoJSON裡的數據進行修改一下,這個地圖就不一樣瞭,這很方便我們在後臺修改地圖。還有這個中國的框架也是數據裡的,總之一句話你看到的這個地圖裡所有元素都是數據裡設置的(除瞭樣式)

這裡寫圖片描述

2、放大縮小地圖和之前效果一樣,值得註意的是我在js中設置瞭顯示級別,就是放大縮小的不同級別顯示的數據也是不同的,比如說那條線吧,我設置在6級以上的才能看到,下面我縮小地圖線就不見瞭,下面是消失瞭的並不是太小看不見的

這裡寫圖片描述

3、在放大到一定級別我設置瞭點的周圍顯示點的名稱!看效果

這裡寫圖片描述

這裡就是加載的效果,下面我們繼續探討。下面就是點擊事件瞭,點擊事件在上篇文章我是著重講瞭原理及實現,而在新技術中我們的點擊事件就很Easy瞭


點擊事件

我們要在map中綁定事件,也就是註冊事件

map.on('singleclick', mapClick);
function mapClick(e) {
    var pixel = map.getEventPixel(e.originalEvent);
    var featureInfo = map.forEachFeatureAtPixel(pixel,
            function(feature, layer) {
                return {
                    feature : feature,
                    layer : layer
                };
            });
    var coordinate = e.coordinate;
    var hdms = ol.coordinate.toStringHDMS(ol.proj.transform(coordinate,
            'EPSG:3857', 'EPSG:4326'));
    if (featureInfo !== undefined && featureInfo !== null
            && featureInfo.layer !== null) {
        if (featureInfo.feature.get("geometry").B.length == 2) {
//          alert(view.getZoom());
            alert(hdms + "\n這裡屬於" + featureInfo.feature.get("name") + "點");
        } else if (featureInfo.feature.get("geometry").B.length == 4) {
            alert(hdms + "\n這裡屬於" + featureInfo.feature.get("name") + "線");
            alert("兩端信息" + featureInfo.feature.get("geometry").B);
        } else {
            // alert(hdms+"\n這裡屬於"+featureInfo.feature.get("name")+"省");//顯示點擊區域的
        }
        console.log('打印選擇要素');
        console.log(featureInfo.feature);
        console.log('打印選擇要素所屬Layer');
        console.log(featureInfo.layer);
    } else {
        alert(hdms + "\n這裡不屬於中國或者這裡是大海");// 顯示點擊區域的
    }
}

在這裡我需要講解一下:

這裡的featureInfo是我們在方法裡拼接的(feature+layer)組成的,在if條件判斷裡我們featureInfo.feature.get(“geometry”).B.length == 2是判斷feature裡數字點的個數,大傢想一想如果是點是不是有兩個數字點,如果是線就是兩個點也就是四個數字點,如果是區域的話那就是至少是超過4的偶數瞭,這樣我們就可以區別出點線和區域瞭,這也就是說我們在這裡就實現瞭之前很難解決的點線問題瞭,區域問題我們就不多加討論瞭。

var hdms = ol.coordinate.toStringHDMS(ol.proj.transform(coordinate,'EPSG:3857', 'EPSG:4326'));

這個是將坐標進行轉換的,這個不多說


定位

在之前我們的定位就是以某個點中心顯示並加上圖標那就是所謂的定位,那麼在我們的新技術中定位是不是有所改變呢?讓我們來一探究竟。

如果你認為既然是新技術瞭就一定要有突破,那麼我的回答可能會讓你很失望,新技術裡仍然是用上述的思想來實現定位的,但多多少少還是有不同的。

新舊對比 openlayers2 openlayers3
點擊 獲取經緯度查詢 點線類別區分
定位 map中心顯示 view中心顯示

由上圖的表格我們可以看出我們的定位還是有所區別的,在新技術中我麼能采用的是view中心顯示法,什麼叫view中心顯示法呢,就是通過view來調用設置中心的方法。

view.setCenter(ol.proj.fromLonLat( [

Number(document.getElementById('jd').value),

Number(document.getElementById('wd').value) ]));

其他常用的事件介紹

事件句柄

HTML 4.0 的新特性之一是有能力使 HTML 事件觸發瀏覽器中的動作(action),比如當用戶點擊某個 HTML 元素時啟動一段 JavaScript。下面是一個屬性列表,這些屬性可插入 HTML 標簽來定義事件動作。

具體事件

屬性 當以下情況發生時,出現此事件 FF N IE
onabort 圖像加載被中斷 1 3 4
onblur 元素失去焦點 1 2 3
onchange 用戶改變域的內容 1 2 3
onclick 鼠標點擊某個對象 1 2 3
ondblclick 鼠標雙擊某個對象 1 4 4
onerror 當加載文檔或圖像時發生某個錯誤 1 3 4
onfocus 元素獲得焦點 1 2 3
onkeydown 某個鍵盤的鍵被按下 1 4 3
onkeypress 某個鍵盤的鍵被按下或按住 1 4 3

此處參考的w3School

在我的地圖中我就隨便加瞭幾個試試效果的。

var select = null; // ref to currently selected interaction
// select interaction working on "singleclick"
var selectSingleClick = new ol.interaction.Select();

// select interaction working on "click"
var selectClick = new ol.interaction.Select( {
    condition : ol.events.condition.click
});

// select interaction working on "pointermove"
var selectPointerMove = new ol.interaction.Select( {
    condition : ol.events.condition.pointerMove
});

var selectAltClick = new ol.interaction.Select( {
    condition : function(mapBrowserEvent) {
        return ol.events.condition.click(mapBrowserEvent)
                && ol.events.condition.altKeyOnly(mapBrowserEvent);
    }
});

var selectElement = document.getElementById('type');

var changeInteraction = function() {
    if (select !== null) {
        map.removeInteraction(select);
    }
    var value = selectElement.value;
    if (value == 'singleclick') {
        select = selectSingleClick;
    } else if (value == 'click') {
        select = selectClick;
    } else if (value == 'pointermove') {
        select = selectPointerMove;
    } else if (value == 'altclick') {
        select = selectAltClick;
    } else {
        select = null;
    }
    if (select !== null) {
        map.addInteraction(select);
        select.on('select', function(e) {
            document.getElementById('status').innerHTML = ' '
                    + e.target.getFeatures().getLength()
                    + ' selected features (last operation selected '
                    + e.selected.length + ' and deselected '
                    + e.deselected.length + ' features)';
        });
    }
};

到這裡整個GeoJSON加載地圖已經講解完畢瞭,上述隻是為瞭幫助各位梳理思路,並不是項目的完整代碼,如果新入門的沒有看明白,可以在博客下方留言,我會將源碼發送給你。

發佈留言