OpenLayers 比較有用的對象和屬性


1.ol.interaction.Pointer

    是管理地圖down、move、up事件的基類,也用於管理地圖拖拽事件。

    構造函數結構如下:

new ol.interaction.Pointer(opt_options)

    options包括的屬性有:
    handleDownEvent:處理地圖的down事件。如果該事件返回true,drag隊列開始執行。

    handleDragEvent:處理地圖的drag事件。當down事件返回true,鼠標在拖拽過程中該事件一直被觸發。

    handleEvent:當地圖通知瀏覽器觸發交互時調用該函數,通過返回FALSE,可終止其他交互事件的傳播。

    handleMoveEvent:在拖拽的過程中觸發move事件。

    handleUpEvent:捕獲鼠標up事件。

2.updateWhileAnimating和updateWhileInteracting屬性

    默認情況下,當在和地圖交互或者動畫過程中,tile和vector圖層會等待這些過程執行完后才會更新。我們可以通過兩個屬性禁止這樣的現象,在vector圖層中,必須在layer級別控制。而像tiled圖層可以直接通過map級別控制。代碼如下:

var map = new ol.Map({
        target: 'map',
        layers: [
            new ol.layer.Tile({
                source: new ol.source.TileWMS({
                    url: 'http://demo.opengeo.org/geoserver/wms',
                    params: {
                        layers: 'ne_50m_land',
                        format: 'image/png'
                    },
                    wrapX: false
                }),
                name: 'Natural Earth Land'
            }),
            new ol.layer.Vector({
                source: new ol.source.Vector({
                    format: new ol.format.GeoJSON({
                        defaultDataProjection: 'EPSG:4326'
                    }),
                    url: '../../res/world_countries.geojson',
                    wrapX: false
                }),
                name: 'World Countries',
                headers: {
                    pop_est: 'integer',
                    gdp_md_est: 'integer'
                },
                type: 'polygon',
                updateWhileAnimating: false,
                updateWhileInteracting: false
            })
        ],
        view: new ol.View({
            center: [0, 0],
            zoom: 2,
            extent: ol.proj.get('EPSG:3857').getExtent()
        }),
        loadTilesWhileAnimating: true,
        loadTilesWhileInteracting: true
    });

3.限制地圖大小屬性

    只要繼承至ol.layer.Base對象的圖層都可通過wrapX:false限制圖層在x軸方向重復;另外也可通過設置view的extend屬性。

    wrapX限制

var map = new ol.Map({
[…]
new ol.layer.Tile({
source: new ol.source.TileWMS({
[…]
wrapX: false
[…]
new ol.layer.Vector({
source: new ol.source.Vector({
[…]
wrapX: false
}),

    extent顯示

view: new ol.View({
[…]
extent: ol.proj.get('EPSG:3857').getExtent()
}),

4.分辨率resolution運算

    在web地圖中,分辨率表示一個像素點表示的單位長度。下面通過一個計算中心點的例如來說明resolution的運算。

map.getView().on('propertychange', function (evt) {
        var projExtent = this.getProjection().getExtent();
        if (projExtent) {
            var currentCenter = this.getCenter();
            var currentResolution = this.getResolution();
            var mapSize = map.getSize();
            var newExtent = [projExtent[0] + currentResolution * mapSize[0] / 2,
                projExtent[1] + currentResolution * mapSize[1] / 2,
                projExtent[2] - currentResolution * mapSize[0] / 2,
                projExtent[3] - currentResolution * mapSize[1] / 2];
            if (!(new ol.geom.Point(currentCenter).intersectsExtent(newExtent))) {
                currentCenter[0] = Math.min(Math.max(currentCenter[0], newExtent[0]), newExtent[2]);
                currentCenter[1] = Math.min(Math.max(currentCenter[1], newExtent[1]), newExtent[3]);
                this.setCenter(currentCenter);
            }
        }
    });

    說明:上面是view各個屬性發生變化時觸發的事件,view.getProjection()獲取投影系對象proj,proj.getExtent()獲取投影系的邊界。view.getResolution()獲取當前視圖的分辨率,currentResolution*mapSize[0]表示整個視圖在經度方向的總長度。geom.intersectsExtent判斷geom是否在extent邊界總。

5.使用unByKey注銷事件

    在很多ol.control.Control控件中我們會注冊一些事件,但經常忽略注銷,下面的方式是比較通用的注銷事件方式:

ol.control.NavigationHistory.prototype.setMap = function (map) {
    ol.control.Control.prototype.setMap.call(this, map);
    if (map === null) {
        ol.Observable.unByKey(this.get('eventId'));
    } else {
        this.set('eventId', map.on('moveend', function (evt) {
            if (this.get('shouldSave')) {
                var view = map.getView();
                var viewStatus = {
                    center: view.getCenter(),
                    resolution: view.getResolution(),
                    rotation: view.getRotation()
                };
                var historyArray = this.get('history');
                var currIndex = this.get('index');
                historyArray.splice(currIndex + 1, historyArray.length - currIndex - 1);
                if (historyArray.length === this.get('maxSize')) {
                    historyArray.splice(0, 1);
                } else {
                    currIndex += 1;
                }
                historyArray.push(viewStatus);
                this.set('index', currIndex);
            } else {
                this.set('shouldSave', true);
            }
        }, this));
    }
};

    當控件和地圖分離時,map會被設置為null,這個時候可調用ol.Observable.unByKey方法取消對事件的監聽。

6.如何改變地圖的投影系

    首先要創建一個新的視圖View,設置view的center、zoom、projection、extent屬性。然后調用map的setView重新替換地圖的視圖。

var view = _this.getMap().getView();
        var oldProj = view.getProjection();
        var newProj = ol.proj.get(this.value);
        var newView = new ol.View({
            center: ol.proj.transform(view.getCenter(), oldProj, newProj),
            zoom: view.getZoom(),
            projection: newProj,
            extent: newProj.getExtent()
        });
        _this.getMap().setView(newView);

    其次需要替換所有圖層的投影系,遍歷所有的圖層,按照圖層的類型采用不同的替換方式。

_this.getMap().getLayers().forEach(function (layer) {
            _this.changeLayerProjection(layer, oldProj, newProj);
        });

    這里的changeLayerProjection是自定義的一個函數,用來處理當個圖層的坐標系。

ol.control.Projection.prototype.changeLayerProjection = function (layer, oldProj, newProj) {
    if (layer instanceof ol.layer.Group) {
        layer.getLayers().forEach(function (subLayer) {
            this.changeLayerProjection(subLayer, oldProj, newProj);
        });
    } else if (layer instanceof ol.layer.Tile) {
        var tileLoadFunc = layer.getSource().getTileLoadFunction();
        layer.getSource().setTileLoadFunction(tileLoadFunc);
    } else if (layer instanceof ol.layer.Vector) {
        var features = layer.getSource().getFeatures();
        for (var i = 0; i < features.length; i += 1) {
            features[i].getGeometry().transform(oldProj, newProj);
        }
    }
};

    layer存在多種類型,所有需要判斷類型分別處理。如果是ol.layer.Group類型,則繼續遍歷分組中的每個圖層;如果圖層類型為ol.layer.Tile瓦片類型,這需要getTileLoadFunction獲取加載函數,重新設置下(由於瓦片圖層有緩存,如果不重新設置加載方式,瓦片圖層還是會從老的坐標系加載瓦片,通過setTileLoadFunction重新設置下加載函數可清理掉瓦片緩存);如果圖層類型為ol.layer.Vector,需要遍歷source中的所有feature,調用feature下geometry的tranform把老坐標系的坐標轉換為新坐標系的坐標。

7.openlayers三種渲染方式

    DOM渲染
    DOM渲染是一種支持預THML5瀏覽器的傳統渲染方式。主要限制在於不能顯示vector圖層,因為vector圖層是使用canvas渲染的。僅僅tile和image圖層能被DOM元素創建。如果必須支持傳統的瀏覽器(不支持canvas),那么openlayers 2是一個不錯的選擇。
    Canvas渲染
    是openlayers 3默認的渲染方式,每個圖層畫在單獨的canvas元素上。
    WEBGL
    WEBGL是瀏覽器對OpenGL的一個現實,瀏覽器有能力使用硬件加速渲染。該技術廣泛用在3D客戶端應用。

8.導出圖層的必備參數

    crossOrigin,ol.source.TileWMS的構造函數有一個參數叫做crossOrigin,如果我們想導出地圖圖片,必須要設置這個參數:

new ol.layer.Tile({
    source: new ol.source.TileWMS({
        url: 'http://demo.opengeo.org/geoserver/wms',
    params: {
        layers: 'nlcd',
    format: 'image/png'
    },
    wrapX: false,
    crossOrigin: 'anonymous'
    }),
    name: 'Land Cover'
})

9.WEBGL

    https://webglfundamentals.org/

10.ol.Geolocation

    獲取地理位置對象,一個HTML5的幫助類,提供HTML5 Geolocation功能。跟蹤終端設備的位置。例如:

var geoloc = new ol.Geolocation({
        projection: map.getView().getProjection(),
        tracking: true
    });
    var geoCaching = new ol.layer.Vector({
        source: new ol.source.Vector()
    });
    map.addLayer(geoCaching);
    geoloc.once('change:position', function (evt) {
        var altitude = this.getAltitude() || 100;
        var myPos = this.getPosition();
        map.getView().setCenter(myPos);
        map.getView().setZoom(17);
        for (var i = 0; i < 50; i += 1) {
            geoCaching.getSource().addFeature(new ol.Feature({
                geometry: new ol.geom.Point([myPos[0] - 500 + Math.random() * 1000, myPos[1] - 500 + Math.random() * 1000, altitude - 150 + Math.random() * 300]),
                loot: 'Treasures of the Seven Seas'
            }));
        }
    });

    說明:geoloc不需要添加到地圖對象上,只需要設置投影系參數。如果想監聽實時位置,可注冊change: position事件。geoloc的getAltitude方法獲取海拔高度。

    Geolocation對象除projection、tracking參數外,還有一個trackingOptions參數,可設置如下:

var geoloc = new ol.Geolocation({
projection: map.getView().getProjection(),
tracking: true,
trackingOptions: {
enableHighAccuracy: true,
maximumAge: 2000
}
});

    enableHighAccuracy允許高精准定位,maximumAge設置定位間隔時間,單位為毫秒。

11.Openlayers 3 shp插件使用

    shp插件支持導入shp文件到openlayers上直接展示。代碼如下:

layerTree.prototype.addVectorLayer = function (form) {
    var file = form.file.files[0];
    var currentProj = this.map.getView().getProjection();
    var fr = new FileReader();
    var sourceFormat = new ol.format.GeoJSON();
    var source = new ol.source.Vector();
    fr.onload = function (evt) {
        var vectorData = evt.target.result;
        var dataProjection = form.projection.value || 

        sourceFormat.readProjection(vectorData) || currentProj;
        shp(vectorData).then(function (geojson) {
            source.addFeatures(sourceFormat.readFeatures(geojson, {
            dataProjection: dataProjection,
            featureProjection: currentProj
            }));
        });
    };
    fr.readAsArrayBuffer(file);
    var layer = new ol.layer.Vector({
        source: source,
        name: form.displayname.value
    });
    this.addBufferIcon(layer);
    this.map.addLayer(layer);
    this.messages.textContent = 'Vector layer added successfully.';
    return this;
};

12.ol.style.Icon

    如何定位圖標,參考下面代碼:

style: new ol.style.Style({
                    image: new ol.style.Icon({
                        /*anchor: [0.5, 46],
                        anchorXUnits: 'fraction',
                        anchorYUnits: 'pixels',*/
                        src: '../../res/marker.png'
                    })
                })

13.Cesium使用

    openlayers團隊封裝了ol3cesium js庫,ol3cesium包含了ol.js代碼,所有我們在使用ol3cesium的時候不用再引用ol.js了。例如:

<script type="text/javascript" src="../../js/ol3-cesium-
1.10.0/Cesium/Cesium.js"></script>
<script type="text/javascript" src="../../js/ol3-cesium-
1.10.0/ol3cesium.js"></script>

    如果我們自定義了ol.js,我們可以在ol3cesium.js引用的后面再引用ol.js即可。例如:

<script type="text/javascript" src="../../js/ol3-cesium-1.10.0/ol3cesium.js"></script>
<script type="text/javascript" src="../../ol/ol.js"></script>

   Cesium場景的可視化非常智能,我們僅僅需要額外定義一個海拔瓦圖源即可。創建代碼如下:

setTimeout(function () {
        var ol3d = new olcs.OLCesium({map: _this.getMap()});
        var scene = ol3d.getCesiumScene();
        scene.terrainProvider = new Cesium.CesiumTerrainProvider({
            url: 'http://assets.agi.com/stk-terrain/world'
        });
        _this.set('cesium', ol3d);
    }, 0);

    可調用cesium.setEnabled方法設置是否可用,setBlockCesiumRendering方法設置是否在后台渲染。 可通過這兩個方法在2D和3D之間切換。

controlButton.addEventListener('click', function (evt) {
        var cesium = _this.get('cesium');
        if (cesium.getEnabled()) {
            cesium.setBlockCesiumRendering(true);
            cesium.setEnabled(false);
        } else {
            cesium.setBlockCesiumRendering(false);
            cesium.setEnabled(true);
        }
    });

14.openlayers 編譯環境

    phtyon必須是2.*的版本,並且配置PYTHON環境變量

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM