OpenLayers3實現(xiàn)測量功能
本文實例為大家分享了OpenLayers3實現(xiàn)測量功能的具體代碼,供大家參考,具體內(nèi)容如下
1. 前言
測量功能實現(xiàn)面積的測量以及長度的測量。通過鼠標繪制區(qū)域以及長度來進行測量。OpenLayers 3 框架沒有提供測量控件,但提供了相應(yīng)的接口,需要需要基于幾何對象的相應(yīng)接口,結(jié)合圖形繪制功能實現(xiàn)。
2. 實現(xiàn)思路
(1)新建一個網(wǎng)頁,引用 openlayers 3 開發(fā)庫、jQuery 庫與 bootstrap 庫,并參照前面顯示地圖的文章,加載 OSM 瓦片圖層。
(2)在地圖容器中,創(chuàng)建一個測量類型選擇控件,進行選擇距離測量與面積測量。
(3)編寫代碼實現(xiàn)測量功能。
3. 實現(xiàn)代碼
html主要代碼
<div id="map"> <div id="menu"> <label>測量類型:</label> <select id="type"> <option value="length">長度</option> <option value="area">面積</option> </select> <label class="checkbox"><input type="checkbox" id="geodesic">使用大地測量</label> </div> </div>
測量類型控件的樣式設(shè)置:
#menu { float: left; position: absolute; bottom: 10px; left: 10px; z-index: 2000; } .checkbox { left: 20px; } /* 提示框的樣式信息 */ .tooltip { position: relative; background: rgba(0, 0, 0, 0.5); border-radius: 4px; color: white; padding: 4px 8px; opacity: 0.7; white-space: nowrap; } .tooltip-measure { opacity: 1; font-weight: bold; } .tooltip-static { background-color: #ffcc33; color: black; border: 1px solid white; } .tooltip-measure::before, .tooltip-static::before { border-top: 6px solid rgb(0, 0, 0, 0.5); border-right: 6px solid transparent; border-left: 6px solid transparent; content: ""; position: absolute; bottom: -6px; margin-left: -7px; left: 50%; } .tooltip-static::before { border-top-color: #ffcc33; }
代碼解析
上面的代碼是結(jié)合 bootstrap庫,使用冒泡提示框形式顯示當(dāng)前的測量結(jié)果,上面的樣式分別設(shè)置了兩種提示框的樣式。
4. 實現(xiàn)測量功能的核心代碼
(1)首先在地圖上加載測量功能的繪制層,即矢量圖層,就相當(dāng)于,我們畫畫,需要紙來進行繪畫,這里的矢量圖層,相當(dāng)于我們的紙。代碼如下:
//加載測量的繪制矢量層 var source = new ol.source.Vector(); //圖層數(shù)據(jù)源 var vector = new ol.layer.Vector({ source: source, style: new ol.style.Style({ //圖層樣式 fill: new ol.style.Fill({ color: 'rgba(255, 255, 255, 0.2)' //填充顏色 }), stroke: new ol.style.Stroke({ color: '#ffcc33', //邊框顏色 width: 2 // 邊框?qū)挾? }), image: new ol.style.Circle({ radius: 7, fill: new ol.style.Fill({ color: '#ffcc33' }) }) }) }); map.addLayer(vector);
(2)通過 addInteraction 方法實現(xiàn)測量功能,首先加載交互繪圖控件(ol.interaction.Draw),也就是我們前面所說的畫畫需要的筆,在測量時根據(jù)測量類型選擇繪制線段或多邊形,然后分別為交互繪圖控件綁定 drawstart 與 drawend 事件。在繪圖開始時實時計算當(dāng)前當(dāng)前繪制線的長度或多邊形的面積,以提示框形式顯示,繪圖結(jié)束時重新創(chuàng)建一個測量提示框顯示測量結(jié)果。通過 addInteraction 函數(shù)實現(xiàn)繪圖測量的代碼:
4.1 addInteraction 函數(shù)實現(xiàn)繪圖測量的代碼:
/** * 切換選擇測量類型(長度或面積) * @param {Event} e Change event. */ typeSelect.onchange = function(e) { map.removeInteraction(draw); //移除繪制圖形 addInteraction(); //添加繪圖進行測量 }; addInteraction(); //調(diào)用加載繪制交互控件的方法,添加繪圖進行測量
addInteraction()函數(shù)代碼:
var geodesicCheckbox = document.getElementById('geodesic'); //測地學(xué)方式對象 var typeSelect = document.getElementById('type'); //測量類型對象 var draw; // global so we can remove it later /** * 加載交互繪制控件函數(shù) */ function addInteraction() { var type = (typeSelect.value == 'area' ? 'Polygon' : 'LineString'); draw = new ol.interaction.Draw({ source: source, //測量繪制層數(shù)據(jù)源 type: /** @type {ol.geom.GeometryType} */ (type), //幾何圖形類型 style: new ol.style.Style({ //繪制幾何圖形的樣式 fill: new ol.style.Fill({ color: 'rgba(255, 255, 255, 0.2)' }), stroke: new ol.style.Stroke({ color: 'rgba(0, 0, 0, 0.5)', lineDash: [10, 10], width: 2 }), image: new ol.style.Circle({ radius: 5, stroke: new ol.style.Stroke({ color: 'rgba(0, 0, 0, 0.7)' }), fill: new ol.style.Fill({ color: 'rgba(255, 255, 255, 0.2)' }) }) }) }); map.addInteraction(draw); createMeasureTooltip(); //創(chuàng)建測量工具提示框 createHelpTooltip(); //創(chuàng)建幫助提示框 var listener; //綁定交互繪制工具開始繪制的事件 draw.on('drawstart', function(evt) { // set sketch sketch = evt.feature; //繪制的要素 /** @type {ol.Coordinate|undefined} */ var tooltipCoord = evt.coordinate; // 繪制的坐標 //綁定change事件,根據(jù)繪制幾何類型得到測量長度值或面積值,并將其設(shè)置到測量工具提示框中顯示 listener = sketch.getGeometry().on('change', function(evt) { var geom = evt.target; //繪制幾何要素 var output; if (geom instanceof ol.geom.Polygon) { output = formatArea( /** @type {ol.geom.Polygon} */ (geom)); //面積值 tooltipCoord = geom.getInteriorPoint().getCoordinates(); //坐標 } else if (geom instanceof ol.geom.LineString) { output = formatLength( /** @type {ol.geom.LineString} */ (geom)); //長度值 tooltipCoord = geom.getLastCoordinate(); //坐標 } measureTooltipElement.innerHTML = output; //將測量值設(shè)置到測量工具提示框中顯示 measureTooltip.setPosition(tooltipCoord); //設(shè)置測量工具提示框的顯示位置 }); }, this); //綁定交互繪制工具結(jié)束繪制的事件 draw.on('drawend', function(evt) { measureTooltipElement.className = 'tooltip tooltip-static'; //設(shè)置測量提示框的樣式 measureTooltip.setOffset([0, -7]); // unset sketch sketch = null; //置空當(dāng)前繪制的要素對象 // unset tooltip so that a new one can be created measureTooltipElement = null; //置空測量工具提示框?qū)ο? createMeasureTooltip(); //重新創(chuàng)建一個測試工具提示框顯示結(jié)果 ol.Observable.unByKey(listener); }, this); }
代碼解析
首先加載繪圖控件(ol.interaction.Draw),也就是我們的筆,在實例化控件時設(shè)置當(dāng)前繪圖要素的樣式,然后分別調(diào)用 createHelpTooltop() 與 createMeasureTooltip() 創(chuàng)建幫助信息提示框和測量工具提示框?qū)ο螅蛔詈蠼壎ɡL圖控件對象的 drawstart 與 drawend 事件,實現(xiàn)繪圖測量功能。其中,在drawstart 事件處理函數(shù)中, 由事件對象得到當(dāng)前繪制的要素(sketch),通過繪制要素的幾何對象綁定 change 事件,根據(jù)事件監(jiān)聽的幾何對象類型是線或是多邊形(ol.geom.Polygon 或 ol.geom.LineString),調(diào)用 formatArea() 與 formatLength() 計算輸出測量得到的面積值或長度值。
4.2 創(chuàng)建提示框的代碼:
/** *創(chuàng)建一個新的幫助提示框(tooltip) */ function createHelpTooltip() { if (helpTooltipElement) { helpTooltipElement.parentNode.removeChild(helpTooltipElement); } helpTooltipElement = document.createElement('div'); helpTooltipElement.className = 'tooltip hidden'; helpTooltip = new ol.Overlay({ element: helpTooltipElement, offset: [15, 0], positioning: 'center-left' }); map.addOverlay(helpTooltip); } /** *創(chuàng)建一個新的測量工具提示框(tooltip) */ function createMeasureTooltip() { if (measureTooltipElement) { measureTooltipElement.parentNode.removeChild(measureTooltipElement); } measureTooltipElement = document.createElement('div'); measureTooltipElement.className = 'tooltip tooltip-measure'; measureTooltip = new ol.Overlay({ element: measureTooltipElement, offset: [0, -15], positioning: 'bottom-center' }); map.addOverlay(measureTooltip); }
代碼解析
基于Openlayers 3 的 ol.Overlay 實現(xiàn)創(chuàng)建幫助信息提示框和測量工具提示框,分別通過 createHelpTooltip() 與 createMeasureTooltip() 創(chuàng)建幫助信息提示框和測量工具提示框, ol.Overlay j就是動態(tài)創(chuàng)建疊加層對象與其目標容器(div層),并將疊加層對象添加到地圖容器中。
4.3 計算長度與面積的代碼:
/** * 測量長度輸出 * @param {ol.geom.LineString} line * @return {string} */ var formatLength = function(line) { var length; if (geodesicCheckbox.checked) { //若使用測地學(xué)方法測量 var coordinates = line.getCoordinates(); //解析線的坐標 length = 0; var sourceProj = map.getView().getProjection(); //地圖數(shù)據(jù)源投影坐標系 //通過遍歷坐標計算兩點之前距離,進而得到整條線的長度 for (var i = 0, ii = coordinates.length - 1; i < ii; ++i) { var c1 = ol.proj.transform(coordinates[i], sourceProj, 'EPSG:4326'); var c2 = ol.proj.transform(coordinates[i + 1], sourceProj, 'EPSG:4326'); length += wgs84Sphere.haversineDistance(c1, c2); } } else { length = Math.round(line.getLength() * 100) / 100; //直接得到線的長度 } var output; if (length > 100) { output = (Math.round(length / 1000 * 100) / 100) + ' ' + 'km'; //換算成KM單位 } else { output = (Math.round(length * 100) / 100) + ' ' + 'm'; //m為單位 } return output; //返回線的長度 }; /** * 測量面積輸出 * @param {ol.geom.Polygon} polygon * @return {string} */ var formatArea = function(polygon) { var area; if (geodesicCheckbox.checked) { //若使用測地學(xué)方法測量 var sourceProj = map.getView().getProjection(); //地圖數(shù)據(jù)源投影坐標系 var geom = /** @type {ol.geom.Polygon} */ (polygon.clone().transform(sourceProj, 'EPSG:4326')); //將多邊形要素坐標系投影為EPSG:4326 var coordinates = geom.getLinearRing(0).getCoordinates(); //解析多邊形的坐標值 area = Math.abs(wgs84Sphere.geodesicArea(coordinates)); //獲取面積 } else { area = polygon.getArea(); //直接獲取多邊形的面積 } var output; if (area > 10000) { output = (Math.round(area / 1000000 * 100) / 100) + ' ' + 'km<sup>2</sup>'; //換算成KM單位 } else { output = (Math.round(area * 100) / 100) + ' ' + 'm<sup>2</sup>'; //m為單位 } return output; //返回多邊形的面積 }; addInteraction(); //調(diào)用加載繪制交互控件方法,添加繪圖進行測量
代碼解析
上面代碼通過 formatLength() 與 formatArea() 分別計算輸出的長度值以及面積值。計算長度值或者面積值時可以通過兩種方法進行計算,一種是使用測地學(xué)的方法基于數(shù)據(jù)的投影坐標系進行計算,另一種是調(diào)用幾何對象或者多邊形對象的方法直接獲取值。
(3)開始畫畫了,分別使用map對象綁定鼠標移動事件(pointermove)和鼠標移除事件(mouseout)。
4.4 添加地圖鼠標移動事件的代碼:
/** * 當(dāng)用戶正在繪制多邊形時的提示信息文本 * @type {string} */ var continuePolygonMsg = '單擊繼續(xù)繪制多邊形'; /** * 當(dāng)用戶正在繪制線時的提示信息文本 * @type {string} */ var continueLineMsg = '單擊繼續(xù)繪制線'; /** * 鼠標移動事件處理函數(shù) * @param {ol.MapBrowserEvent} evt */ var pointerMoveHandler = function(evt) { if (evt.dragging) { return; } /** @type {string} */ var helpMsg = '開始繪制'; //當(dāng)前默認提示信息 //判斷繪制幾何類型設(shè)置相應(yīng)的幫助提示信息 if (sketch) { var geom = (sketch.getGeometry()); if (geom instanceof ol.geom.Polygon) { helpMsg = continuePolygonMsg; //繪制多邊形時提示相應(yīng)內(nèi)容 } else if (geom instanceof ol.geom.LineString) { helpMsg = continueLineMsg; //繪制線時提示相應(yīng)內(nèi)容 } } helpTooltipElement.innerHTML = helpMsg; //將提示信息設(shè)置到對話框中顯示 helpTooltip.setPosition(evt.coordinate); //設(shè)置幫助提示框的位置 $(helpTooltipElement).removeClass('hidden'); //移除幫助提示框的隱藏樣式進行顯示 }; map.on('pointermove', pointerMoveHandler); //地圖容器綁定鼠標移動事件,動態(tài)顯示幫助提示框內(nèi)容 //地圖綁定鼠標移出事件,鼠標移出時為幫助提示框設(shè)置隱藏樣式 $(map.getViewport()).on('mouseout', function() { $(helpTooltipElement).addClass('hidden'); });
代碼解析
鼠標移動事件(pointermove),在回調(diào)函數(shù)中,根據(jù)用戶選擇測量的類型,在彈窗中顯示幫助提示信息,同時為地圖容器綁定鼠標移除事件(mouseout),該事件發(fā)生后影藏提示框。
5. 實現(xiàn)效果
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
基于Ionic3實現(xiàn)選項卡切換并重新加載echarts
這篇文章主要介紹了基于Ionic3實現(xiàn)選項卡切換并重新加載echarts,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-09-09關(guān)于AOP在JS中的實現(xiàn)與應(yīng)用詳解
這篇文章主要給大家介紹了關(guān)于AOP在JS中的實現(xiàn)與應(yīng)用的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用JS具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05JavaScript中函數(shù)表達式和函數(shù)聲明及函數(shù)聲明與函數(shù)表達式的不同
這篇文章主要介紹了JavaScript中函數(shù)表達式和函數(shù)聲明及函數(shù)聲明與函數(shù)表達式的不同的相關(guān)資料,需要的朋友可以參考下2015-11-11