1. 程式人生 > >OpenLayer基礎(二)——圖層(layer)

OpenLayer基礎(二)——圖層(layer)

在openlayers中,Layer是Map的必須組成,也是核心要素,今天學習利用openlayers載入各種不同型別的地圖資料。內容包括:

  • 利用openlayers載入瓦片資料;
  • 利用openlayers載入圖片資料
  • 利用openlayers載入向量資料
  • 利用openlayers載入向量瓦片資料

1.Layer

ol定義了四種基本的圖層型別,分別是Tile、Image、Vector、VectorTile,這四種類有一個共同的基類Layer,它們的大多數屬性和方法都繼承自這個類。下面是ol對Layer類的定義:

Abstract base class; normally only used for creating subclasses and not
instantiated in apps.A visual representation of raster or vector map data.
Layers group together those properties that pertain to how the data is to be
displayed, irrespective of the source of that data.

Layer的主要屬性:

  • opacity,不透明度,預設為 1 ,即完全不透明;
  • zIndex,圖層的疊放次序,預設為0,值最小的圖層位於最下方;
  • visible,是否可見,預設為 true ;
  • extent,圖層渲染的區域,格式為[minx,miny,maxx,maxy]。如果沒有設定該引數,圖層就不會顯示;
  • minResolution,最小解析度,當圖層的縮放級別小於這個解析度時,圖層就會隱藏;
  • maxResolution,最大解析度,當圖層的縮放級別等於或超過這個解析度時,圖層就會隱藏;
  • source,圖層的來源。

Layer的主要方法:

  • getLayersArray(),得到所有圖層;
  • getLayerStatesArray(),得到所有圖層狀態;
  • getSource(),得到相應圖層的來源;
  • getSourceState(),得到相應圖層的來源狀態;
  • setSource(),設定圖層 source 屬性,引數為一個 source 物件;
  • setMap(),新增Layer到Map,並由Map管理。

2. Tile/TileLayer

Tile指瓦片資料,是WebGIS最常用的資料型別,TileLayer在繼承Tile所有屬性和方法的同時自己定義了preload屬性以及對應的getPreload()setPreload()方法,preload指低解析度瓦片預載入的等級,預設為0,即不預載入。顯示任何一幅地圖需要3個要素:

  1. 容器,即地圖顯示在什麼地方;
  2. 資料來源,即顯示哪個資料;
  3. 檢視,即地圖的座標、範圍和等級。

所以,利用ol顯示瓦片資料的過程是:

  • 建立容器並定義地圖,和leaflet一樣,地圖必須顯示在一個div中,因此首先建立一個div:<div id="map" class="map"></div>
  • 定義資料來源,即建立TileLayer(當然ol中圖層和資料來源是兩個不同的類,這裡就放在一起了):
var layer=new ol.layer.Tile({
        source: new ol.source.OSM(),
        visible:true,
        opacity:0.8,
        zIndex: 1
    })
  • 定義檢視,檢視和資料來源息息相關,不可分離:
var view=new ol.View({
        center:ol.projfromLonLat([37.41, 8.82]),
        zoom:4
    })

-建立地圖

var map = new ol.Map({
        target: 'map',
        layers: [
            layer
        ],
        view: view
    });

到此,已經完成了顯示一個瓦片資料的全部過程。關於以上程式碼:

  • 和leaflet一樣,地圖必須顯示在一個div中。
  • target:'map'指定了地圖要顯示在id為map的div中
  • new ol.layer.Tile({ source: new ol.source.OSM() })定義了一個圖層,資料來源是OpenStreetMap提供的切片資料。
  • new ol.View({ center: ol.proj.fromLonLat([37.41, 8.82]), zoom: 4 }) 定義了地圖的中心位置,範圍和層級。
  • ol.proj.fromLonLat([37.41, 8.82]) 是將一個經緯度座標轉換成投影座標。
fromLonLat(coordinate, opt_projection)
coordinate:經緯度座標
projection:目標投影,預設Web Mercator,'EPSG:3857'

3. Image/ImageLayer

Image指圖片資料,ol可以將網路或本地的圖片載入到網頁中,ImageLayer並沒有增加任何屬性和方法,載入一個圖片資料,需要兩個必要引數:一是extent,另一個是projection。現在我有一個生態系統分佈的圖片,首先,利用ArcGIS開啟地圖資料,獲得其範圍和座標系。
在這裡插入圖片描述
根據上圖定義extent和projection:

 var extent=[-1834184.237800,2231702.381200,-672568.125000,2845554.176000]
var proj=new ol.proj.Projection({
        code:'EPSG:102025',
        extent:extent
    })

然後將圖片載入到網頁中:

var map = new ol.Map({
        target: 'map',
        layers: [
            new ol.layer.Image(
                {
                    source:new ol.source.ImageStatic({
                        url:'../img/2015.jpg',
                        projection:proj,
                        imageExtent: extent
                    })
                }
            )
        ],
        view: new ol.View({
            center: ol.extent.getCenter(extent),
            //center:ol.proj.fromLonLat([98,34],proj),
            projection:proj,
            zoom: 1
        })
    });

在這裡插入圖片描述

4.Vector/VectorLayer

Vector指向量資料,VectorLayer自己定義了很多屬性和方法:

  • renderOrder:渲染地理要素時的順序,一般情況下,在渲染之前,要素是基於一定規則排序的,而渲染就是根據這個順序進行依次渲染的,這個引數便指定了這個排序規則,如果賦值為 null ,那麼就不會對地理要素進行排序,渲染也不會有一定的順序;
  • renderBuffer:預設值為100;
  • style:規定了向量圖層的樣式,即配色、形狀等;
  • renderMode:渲染模式,Image表示資料被渲染為影象,點和文字資訊會隨影象旋轉,縮放時畫素也會被縮放;Vector表示將資料渲染為向量,最精確但效能較慢。
  • updateWhileAnimating:當有動畫特效時,地理要素是否被重新建立,預設是 false;
  • updateWhileInteracting:當地理要素互動時,是否重新渲染。

openlayers載入向量資料需要轉換成GeoJSON格式,以shp資料為例,先將資料轉換成GeoJSON格式,轉換方法很多,推薦兩種:一是利用QGIS另存為功能,二是利用python geopandas的to_josn()方法,批量轉換時推薦。ol載入GeoJSON的和前兩種大同小異:

var map = new ol.Map({
        target: 'map',
        layers: [
            new ol.layer.Vector(
                {
                    source: new ol.source.Vector({
                        projcetion: 'EPSG:4326',
                        url: '../data/glass.geojson',
                        format: new ol.format.GeoJSON()
                    })
                }
            )
        ],
        view: new ol.View({
            center: [11046067.83154739,4094171.054588544],
            zoom: 6,
            projcetion: "EPSG:4326"
        })
    });

如果要自己定義圖層樣式:

var fill = new ol.style.Fill({
        color: 'rgba(255,123,100,0.8)'
         });
var stroke = new ol.style.Stroke({
        color: '#3399CC',
        width: 1.25
          });
var styles =
        new ol.style.Style({
            image: new ol.style.Circle({
                fill: fill,
                stroke: stroke,
                radius: 4
                }),
           fill: fill,
           stroke: stroke
       })
var map = new ol.Map({
        target: 'map',
        layers: [
            new ol.layer.Vector(
                {
                    source: new ol.source.Vector({
                        projcetion: 'EPSG:4326',
                        url: '../data/glass.geojson',
                        format: new ol.format.GeoJSON()
                    }),
                    style:styles

                }
            )
        ],
        view: new ol.View({
            center: [11046067.83154739,4094171.054588544],
            zoom: 6,
            projcetion: "EPSG:4326"
        })
    });

展示一下效果:
在這裡插入圖片描述

5. Vector/VectorLayer

已經快凌晨了,累的不行了,直接上程式碼

var key = 'Your Mapbox access token from http://mapbox.com/ here';

    var map = new ol.Map({
        layers: [
            new ol.layer.VectorTile({
                declutter: true,
                source: new ol.source.VectorTile({
                    attributions: '© <a href="https://www.mapbox.com/map-feedback/">Mapbox</a> ' +
                        '© <a href="https://www.openstreetmap.org/copyright">' +
                        'OpenStreetMap contributors</a>',
                    format: new ol.format.MVT(),
                    url: 'https://{a-d}.tiles.mapbox.com/v4/mapbox.mapbox-streets-v6/' +
                        '{z}/{x}/{y}.vector.pbf?access_token=' + key
                }),
                style: createMapboxStreetsV6Style(ol.style.Style, ol.source.Fill, ol.style.Stroke, ol.style.Icon, ol.style.Text)
            })
        ],
        target: 'map',
        view: new ol.View({
            center: [0, 0],
            zoom: 2
        })
    })

後記:現在是凌晨5點整,Firefox瀏覽器坑我,好幾次崩潰讓我前功盡棄,以後要考慮換瀏覽器了。學習了openlayer第一個感覺就是比leaflet要難很多,也要強大很多,後面有時間會繼續更新,晚安。