OpenLayers3實(shí)現(xiàn)測(cè)量功能
本文實(shí)例為大家分享了OpenLayers3實(shí)現(xiàn)測(cè)量功能的具體代碼,供大家參考,具體內(nèi)容如下
1. 前言
測(cè)量功能實(shí)現(xiàn)面積的測(cè)量以及長(zhǎng)度的測(cè)量。通過(guò)鼠標(biāo)繪制區(qū)域以及長(zhǎng)度來(lái)進(jìn)行測(cè)量。OpenLayers 3 框架沒(méi)有提供測(cè)量控件,但提供了相應(yīng)的接口,需要需要基于幾何對(duì)象的相應(yīng)接口,結(jié)合圖形繪制功能實(shí)現(xiàn)。
2. 實(shí)現(xiàn)思路
(1)新建一個(gè)網(wǎng)頁(yè),引用 openlayers 3 開(kāi)發(fā)庫(kù)、jQuery 庫(kù)與 bootstrap 庫(kù),并參照前面顯示地圖的文章,加載 OSM 瓦片圖層。
(2)在地圖容器中,創(chuàng)建一個(gè)測(cè)量類(lèi)型選擇控件,進(jìn)行選擇距離測(cè)量與面積測(cè)量。
(3)編寫(xiě)代碼實(shí)現(xiàn)測(cè)量功能。
3. 實(shí)現(xiàn)代碼
html主要代碼
<div id="map"> <div id="menu"> <label>測(cè)量類(lèi)型:</label> <select id="type"> <option value="length">長(zhǎng)度</option> <option value="area">面積</option> </select> <label class="checkbox"><input type="checkbox" id="geodesic">使用大地測(cè)量</label> </div> </div>
測(cè)量類(lèi)型控件的樣式設(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庫(kù),使用冒泡提示框形式顯示當(dāng)前的測(cè)量結(jié)果,上面的樣式分別設(shè)置了兩種提示框的樣式。
4. 實(shí)現(xiàn)測(cè)量功能的核心代碼
(1)首先在地圖上加載測(cè)量功能的繪制層,即矢量圖層,就相當(dāng)于,我們畫(huà)畫(huà),需要紙來(lái)進(jìn)行繪畫(huà),這里的矢量圖層,相當(dāng)于我們的紙。代碼如下:
//加載測(cè)量的繪制矢量層 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)通過(guò) addInteraction 方法實(shí)現(xiàn)測(cè)量功能,首先加載交互繪圖控件(ol.interaction.Draw),也就是我們前面所說(shuō)的畫(huà)畫(huà)需要的筆,在測(cè)量時(shí)根據(jù)測(cè)量類(lèi)型選擇繪制線段或多邊形,然后分別為交互繪圖控件綁定 drawstart 與 drawend 事件。在繪圖開(kāi)始時(shí)實(shí)時(shí)計(jì)算當(dāng)前當(dāng)前繪制線的長(zhǎng)度或多邊形的面積,以提示框形式顯示,繪圖結(jié)束時(shí)重新創(chuàng)建一個(gè)測(cè)量提示框顯示測(cè)量結(jié)果。通過(guò) addInteraction 函數(shù)實(shí)現(xiàn)繪圖測(cè)量的代碼:
4.1 addInteraction 函數(shù)實(shí)現(xiàn)繪圖測(cè)量的代碼:
/** * 切換選擇測(cè)量類(lèi)型(長(zhǎng)度或面積) * @param {Event} e Change event. */ typeSelect.onchange = function(e) { map.removeInteraction(draw); //移除繪制圖形 addInteraction(); //添加繪圖進(jìn)行測(cè)量 }; addInteraction(); //調(diào)用加載繪制交互控件的方法,添加繪圖進(jìn)行測(cè)量
addInteraction()函數(shù)代碼:
var geodesicCheckbox = document.getElementById('geodesic'); //測(cè)地學(xué)方式對(duì)象 var typeSelect = document.getElementById('type'); //測(cè)量類(lèi)型對(duì)象 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, //測(cè)量繪制層數(shù)據(jù)源 type: /** @type {ol.geom.GeometryType} */ (type), //幾何圖形類(lèi)型 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)建測(cè)量工具提示框 createHelpTooltip(); //創(chuàng)建幫助提示框 var listener; //綁定交互繪制工具開(kāi)始繪制的事件 draw.on('drawstart', function(evt) { // set sketch sketch = evt.feature; //繪制的要素 /** @type {ol.Coordinate|undefined} */ var tooltipCoord = evt.coordinate; // 繪制的坐標(biāo) //綁定change事件,根據(jù)繪制幾何類(lèi)型得到測(cè)量長(zhǎng)度值或面積值,并將其設(shè)置到測(cè)量工具提示框中顯示 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(); //坐標(biāo) } else if (geom instanceof ol.geom.LineString) { output = formatLength( /** @type {ol.geom.LineString} */ (geom)); //長(zhǎng)度值 tooltipCoord = geom.getLastCoordinate(); //坐標(biāo) } measureTooltipElement.innerHTML = output; //將測(cè)量值設(shè)置到測(cè)量工具提示框中顯示 measureTooltip.setPosition(tooltipCoord); //設(shè)置測(cè)量工具提示框的顯示位置 }); }, this); //綁定交互繪制工具結(jié)束繪制的事件 draw.on('drawend', function(evt) { measureTooltipElement.className = 'tooltip tooltip-static'; //設(shè)置測(cè)量提示框的樣式 measureTooltip.setOffset([0, -7]); // unset sketch sketch = null; //置空當(dāng)前繪制的要素對(duì)象 // unset tooltip so that a new one can be created measureTooltipElement = null; //置空測(cè)量工具提示框?qū)ο? createMeasureTooltip(); //重新創(chuàng)建一個(gè)測(cè)試工具提示框顯示結(jié)果 ol.Observable.unByKey(listener); }, this); }
代碼解析
首先加載繪圖控件(ol.interaction.Draw),也就是我們的筆,在實(shí)例化控件時(shí)設(shè)置當(dāng)前繪圖要素的樣式,然后分別調(diào)用 createHelpTooltop() 與 createMeasureTooltip() 創(chuàng)建幫助信息提示框和測(cè)量工具提示框?qū)ο?;最后綁定繪圖控件對(duì)象的 drawstart 與 drawend 事件,實(shí)現(xiàn)繪圖測(cè)量功能。其中,在drawstart 事件處理函數(shù)中, 由事件對(duì)象得到當(dāng)前繪制的要素(sketch),通過(guò)繪制要素的幾何對(duì)象綁定 change 事件,根據(jù)事件監(jiān)聽(tīng)的幾何對(duì)象類(lèi)型是線或是多邊形(ol.geom.Polygon 或 ol.geom.LineString),調(diào)用 formatArea() 與 formatLength() 計(jì)算輸出測(cè)量得到的面積值或長(zhǎng)度值。
4.2 創(chuàng)建提示框的代碼:
/** *創(chuàng)建一個(gè)新的幫助提示框(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)建一個(gè)新的測(cè)量工具提示框(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 實(shí)現(xiàn)創(chuàng)建幫助信息提示框和測(cè)量工具提示框,分別通過(guò) createHelpTooltip() 與 createMeasureTooltip() 創(chuàng)建幫助信息提示框和測(cè)量工具提示框, ol.Overlay j就是動(dòng)態(tài)創(chuàng)建疊加層對(duì)象與其目標(biāo)容器(div層),并將疊加層對(duì)象添加到地圖容器中。
4.3 計(jì)算長(zhǎng)度與面積的代碼:
/** * 測(cè)量長(zhǎng)度輸出 * @param {ol.geom.LineString} line * @return {string} */ var formatLength = function(line) { var length; if (geodesicCheckbox.checked) { //若使用測(cè)地學(xué)方法測(cè)量 var coordinates = line.getCoordinates(); //解析線的坐標(biāo) length = 0; var sourceProj = map.getView().getProjection(); //地圖數(shù)據(jù)源投影坐標(biāo)系 //通過(guò)遍歷坐標(biāo)計(jì)算兩點(diǎn)之前距離,進(jìn)而得到整條線的長(zhǎng)度 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; //直接得到線的長(zhǎng)度 } 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; //返回線的長(zhǎng)度 }; /** * 測(cè)量面積輸出 * @param {ol.geom.Polygon} polygon * @return {string} */ var formatArea = function(polygon) { var area; if (geodesicCheckbox.checked) { //若使用測(cè)地學(xué)方法測(cè)量 var sourceProj = map.getView().getProjection(); //地圖數(shù)據(jù)源投影坐標(biāo)系 var geom = /** @type {ol.geom.Polygon} */ (polygon.clone().transform(sourceProj, 'EPSG:4326')); //將多邊形要素坐標(biāo)系投影為EPSG:4326 var coordinates = geom.getLinearRing(0).getCoordinates(); //解析多邊形的坐標(biāo)值 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)用加載繪制交互控件方法,添加繪圖進(jìn)行測(cè)量
代碼解析
上面代碼通過(guò) formatLength() 與 formatArea() 分別計(jì)算輸出的長(zhǎng)度值以及面積值。計(jì)算長(zhǎng)度值或者面積值時(shí)可以通過(guò)兩種方法進(jìn)行計(jì)算,一種是使用測(cè)地學(xué)的方法基于數(shù)據(jù)的投影坐標(biāo)系進(jìn)行計(jì)算,另一種是調(diào)用幾何對(duì)象或者多邊形對(duì)象的方法直接獲取值。
(3)開(kāi)始畫(huà)畫(huà)了,分別使用map對(duì)象綁定鼠標(biāo)移動(dòng)事件(pointermove)和鼠標(biāo)移除事件(mouseout)。
4.4 添加地圖鼠標(biāo)移動(dòng)事件的代碼:
/** * 當(dāng)用戶正在繪制多邊形時(shí)的提示信息文本 * @type {string} */ var continuePolygonMsg = '單擊繼續(xù)繪制多邊形'; /** * 當(dāng)用戶正在繪制線時(shí)的提示信息文本 * @type {string} */ var continueLineMsg = '單擊繼續(xù)繪制線'; /** * 鼠標(biāo)移動(dòng)事件處理函數(shù) * @param {ol.MapBrowserEvent} evt */ var pointerMoveHandler = function(evt) { if (evt.dragging) { return; } /** @type {string} */ var helpMsg = '開(kāi)始繪制'; //當(dāng)前默認(rèn)提示信息 //判斷繪制幾何類(lèi)型設(shè)置相應(yīng)的幫助提示信息 if (sketch) { var geom = (sketch.getGeometry()); if (geom instanceof ol.geom.Polygon) { helpMsg = continuePolygonMsg; //繪制多邊形時(shí)提示相應(yīng)內(nèi)容 } else if (geom instanceof ol.geom.LineString) { helpMsg = continueLineMsg; //繪制線時(shí)提示相應(yīng)內(nèi)容 } } helpTooltipElement.innerHTML = helpMsg; //將提示信息設(shè)置到對(duì)話框中顯示 helpTooltip.setPosition(evt.coordinate); //設(shè)置幫助提示框的位置 $(helpTooltipElement).removeClass('hidden'); //移除幫助提示框的隱藏樣式進(jìn)行顯示 }; map.on('pointermove', pointerMoveHandler); //地圖容器綁定鼠標(biāo)移動(dòng)事件,動(dòng)態(tài)顯示幫助提示框內(nèi)容 //地圖綁定鼠標(biāo)移出事件,鼠標(biāo)移出時(shí)為幫助提示框設(shè)置隱藏樣式 $(map.getViewport()).on('mouseout', function() { $(helpTooltipElement).addClass('hidden'); });
代碼解析
鼠標(biāo)移動(dòng)事件(pointermove),在回調(diào)函數(shù)中,根據(jù)用戶選擇測(cè)量的類(lèi)型,在彈窗中顯示幫助提示信息,同時(shí)為地圖容器綁定鼠標(biāo)移除事件(mouseout),該事件發(fā)生后影藏提示框。
5. 實(shí)現(xiàn)效果
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
純?cè)鷍s實(shí)現(xiàn)table表格的增刪
本文主要介紹了純?cè)鷍avascript實(shí)現(xiàn)table表格的增刪的方法,文章底部提供了完整的代碼。需要的朋友一起來(lái)看下吧2017-01-01基于Ionic3實(shí)現(xiàn)選項(xiàng)卡切換并重新加載echarts
這篇文章主要介紹了基于Ionic3實(shí)現(xiàn)選項(xiàng)卡切換并重新加載echarts,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09js實(shí)現(xiàn)計(jì)算器和計(jì)時(shí)器功能
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)計(jì)算器和計(jì)時(shí)器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07關(guān)于AOP在JS中的實(shí)現(xiàn)與應(yīng)用詳解
這篇文章主要給大家介紹了關(guān)于AOP在JS中的實(shí)現(xiàn)與應(yīng)用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用JS具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05JavaScript中函數(shù)表達(dá)式和函數(shù)聲明及函數(shù)聲明與函數(shù)表達(dá)式的不同
這篇文章主要介紹了JavaScript中函數(shù)表達(dá)式和函數(shù)聲明及函數(shù)聲明與函數(shù)表達(dá)式的不同的相關(guān)資料,需要的朋友可以參考下2015-11-11axios實(shí)現(xiàn)簡(jiǎn)單文件上傳功能
這篇文章主要為大家詳細(xì)介紹了axios實(shí)現(xiàn)簡(jiǎn)單文件上傳功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09