場景
Vue+Openlayer使用Draw實現交互式繪制線段:
https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/121287934
在上面已經實現交互式繪制線段基礎上,怎樣實現測量距離。

注:
博客:
https://blog.csdn.net/badao_liumang_qizhi
關注公眾號
霸道的程序猿
獲取編程相關電子書、教程推送與免費下載。
實現
1、頁面上添加按鈕與map
<template>
<div>
<div>
<el-button type="primary" @click="beginCalDistance">開始測距</el-button>
<el-button type="primary" @click="cancleCalDistance">取消測距</el-button>
</div>
<div id="app">
<div id="map" class="map"></div>
</div>
</div>
</template>
2、引入相關依賴
//導入基本模塊 import "ol/ol.css"; import Map from "ol/Map"; import View from "ol/View"; import { Fill, Style, Stroke } from "ol/style"; //導入相關模塊 import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer"; import { TileWMS, Vector as VectorSource } from "ol/source"; import { Select, Draw } from "ol/interaction"; import { getLength } from "ol/sphere"; import { LineString } from "ol/geom"; import Overlay from "ol/Overlay";
3、聲明變量
export default { name: "olMapImageWMSDrawLineAndCalDistance", data() { return { map: null, // map地圖 layer: null, //地圖圖層 lineLayer: null, //線圖層 draw: null, lineSource: null, coordinate: [], measureTooltipElement: null, measureTooltip: null, sketch: null, geom: null, }; },
4、在頁面初始化之后調用初始化地圖的方法
//初始化地圖 initMap() { //地圖圖層 this.layer = new TileLayer({ source: new TileWMS({ //不能設置為0,否則地圖不展示。 ratio: 1, url: "http://localhost:8000/geoserver/nyc/wms", params: { LAYERS: "nyc:nyc_roads", STYLES: "", VERSION: "1.1.1", tiled: true, }, serverType: "geoserver", }), }); //線的圖層 this.lineSource = new VectorSource({ wrapX: false }); this.lineLayer = new VectorLayer({ source: this.lineSource, }); this.map = new Map({ //地圖容器ID target: "map", //引入地圖 layers: [this.layer, this.lineLayer], view: new View({ //地圖中心點 center: [987777.93778, 213834.81024], zoom: 14, minZoom: 6, // 地圖縮放最小級別 maxZoom: 19, }), }); },
5、開始測試按鈕的點擊事件中
//開始測距 beginCalDistance() { //調用繪圖工具並傳遞類型為線,其他類型有Point,LineString,Polygon,Circle this.onAddInteraction("LineString"); //創建一個新的測距提示 this.createMeasureTooltip(); },
調用繪圖功能並傳遞類型為線以及給地圖添加交互onAddInteraction方法
// 繪圖工具 onAddInteraction(type) { let self = this; //勾繪矢量圖形的類 this.draw = new Draw({ //source代表勾繪的要素屬於的數據集 source: self.lineSource, //type 表示勾繪的要素包含的 geometry 類型 type: type, }); //繪制開始時觸發的事件 this.draw.on("drawstart", function (evt) { self.sketch = evt.feature; //提示框的坐標 var tooltipCoord = evt.coordinate; //定義一個事件監聽,監聽幾何要素的change事件 var listener = self.sketch.getGeometry().on("change", function (evt) { //獲取繪制的幾何對象 self.geom = evt.target; //定義一個輸出對象,用於記錄長度 var output; //判斷交互類型是否為線 if (self.geom instanceof LineString) { //輸出多線段的長度 output = self.formatLength(self.geom); //獲取多線段的最后一個點的坐標 tooltipCoord = self.geom.getLastCoordinate(); } //設置測量提示框的內標簽為最終輸出結果 self.measureTooltipElement.innerHTML = output; self.measureTooltipElement.className = "ol-tooltip ol-tooltip-static draw_km"; //設置測量提示框的位置坐標 self.measureTooltip.setPosition(tooltipCoord); }); }); //繪制結束時觸發的事件 this.draw.on("drawend", function (e) { //輸出坐標信息 const geometry = e.feature.getGeometry(); let pointArr = geometry.getCoordinates(); self.coordinate.push(pointArr); console.log("self.coordinate=" + self.coordinate); //移除交互 self.removeDraw(); }); //添加交互 self.map.addInteraction(this.draw); },
創建測距提示的方法createMeasureTooltip
//創建一個新的測距提示 createMeasureTooltip() { let self = this; //如果已經存在幫助提示框則移除 if (self.measureTooltipElement) { self.measureTooltipElement.parentNode.removeChild( self.measureTooltipElement ); } //創建幫助提示要素的div self.measureTooltipElement = document.createElement("div"); //設置幫助提示要素的樣式 self.measureTooltipElement.className = "ol-tooltip ol-tooltip-measure"; //創建一個幫助提示的覆蓋標注 self.measureTooltip = new Overlay({ element: self.measureTooltipElement, offset: [0, -15], positioning: "bottom-center", }); //將幫助提示的覆蓋標注添加到地圖中 self.map.addOverlay(self.measureTooltip); },
其中又用到測量距離的方法formatLength
// 測量距離 formatLength(line) { //計算平面距離 var length = getLength(line); //定義輸出變量 var output; //如果長度大於1000,則使用km單位,否則使用m單位 if (length > 1000) { output = Math.round((length / 1000) * 100) / 100 + " " + "km"; } else { output = Math.round(length * 100) / 100 + " " + "m"; } return output; },
6、取消測距方法的點擊事件
// 取消測距 cancleCalDistance() { let self = this; this.map.removeInteraction(this.draw); this.lineSource.clear(); let layerArr = this.map.getOverlays(); var deleteOverlayArr = []; layerArr.forEach((item) => { if ( item.values_.element.className === "ol-tooltip ol-tooltip-static draw_km" ) { deleteOverlayArr.push(item); } }); deleteOverlayArr.forEach((item) => { self.map.removeOverlay(item); }); },
7、完整示例代碼
<template>
<div>
<div>
<el-button type="primary" @click="beginCalDistance">開始測距</el-button>
<el-button type="primary" @click="cancleCalDistance">取消測距</el-button>
</div>
<div id="app">
<div id="map" class="map"></div>
</div>
</div>
</template>
<script>
//導入基本模塊
import "ol/ol.css";
import Map from "ol/Map";
import View from "ol/View";
import { Fill, Style, Stroke } from "ol/style";
//導入相關模塊
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import { TileWMS, Vector as VectorSource } from "ol/source";
import { Select, Draw } from "ol/interaction";
import { getLength } from "ol/sphere";
import { LineString } from "ol/geom";
import Overlay from "ol/Overlay";
export default {
name: "olMapImageWMSDrawLineAndCalDistance",
data() {
return {
map: null, // map地圖
layer: null, //地圖圖層
lineLayer: null, //線圖層
draw: null,
lineSource: null,
coordinate: [],
measureTooltipElement: null,
measureTooltip: null,
sketch: null,
geom: null,
};
},
mounted() {
this.initMap();
},
methods: {
//開始測距
beginCalDistance() {
//調用繪圖工具並傳遞類型為線,其他類型有Point,LineString,Polygon,Circle
this.onAddInteraction("LineString");
//創建一個新的測距提示
this.createMeasureTooltip();
},
// 取消測距
cancleCalDistance() {
let self = this;
this.map.removeInteraction(this.draw);
this.lineSource.clear();
let layerArr = this.map.getOverlays();
var deleteOverlayArr = [];
layerArr.forEach((item) => {
if (
item.values_.element.className ===
"ol-tooltip ol-tooltip-static draw_km"
) {
deleteOverlayArr.push(item);
}
});
deleteOverlayArr.forEach((item) => {
self.map.removeOverlay(item);
});
},
// 繪圖工具
onAddInteraction(type) {
let self = this;
//勾繪矢量圖形的類
this.draw = new Draw({
//source代表勾繪的要素屬於的數據集
source: self.lineSource,
//type 表示勾繪的要素包含的 geometry 類型
type: type,
});
//繪制開始時觸發的事件
this.draw.on("drawstart", function (evt) {
self.sketch = evt.feature;
//提示框的坐標
var tooltipCoord = evt.coordinate;
//定義一個事件監聽,監聽幾何要素的change事件
var listener = self.sketch.getGeometry().on("change", function (evt) {
//獲取繪制的幾何對象
self.geom = evt.target;
//定義一個輸出對象,用於記錄長度
var output;
//判斷交互類型是否為線
if (self.geom instanceof LineString) {
//輸出多線段的長度
output = self.formatLength(self.geom);
//獲取多線段的最后一個點的坐標
tooltipCoord = self.geom.getLastCoordinate();
}
//設置測量提示框的內標簽為最終輸出結果
self.measureTooltipElement.innerHTML = output;
self.measureTooltipElement.className =
"ol-tooltip ol-tooltip-static draw_km";
//設置測量提示框的位置坐標
self.measureTooltip.setPosition(tooltipCoord);
});
});
//繪制結束時觸發的事件
this.draw.on("drawend", function (e) {
//輸出坐標信息
const geometry = e.feature.getGeometry();
let pointArr = geometry.getCoordinates();
self.coordinate.push(pointArr);
console.log("self.coordinate=" + self.coordinate);
//移除交互
self.removeDraw();
});
//添加交互
self.map.addInteraction(this.draw);
},
//刪除交互
removeDraw() {
this.map.removeInteraction(this.draw);
},
//創建一個新的測距提示
createMeasureTooltip() {
let self = this;
//如果已經存在幫助提示框則移除
if (self.measureTooltipElement) {
self.measureTooltipElement.parentNode.removeChild(
self.measureTooltipElement
);
}
//創建幫助提示要素的div
self.measureTooltipElement = document.createElement("div");
//設置幫助提示要素的樣式
self.measureTooltipElement.className = "ol-tooltip ol-tooltip-measure";
//創建一個幫助提示的覆蓋標注
self.measureTooltip = new Overlay({
element: self.measureTooltipElement,
offset: [0, -15],
positioning: "bottom-center",
});
//將幫助提示的覆蓋標注添加到地圖中
self.map.addOverlay(self.measureTooltip);
},
//初始化地圖
initMap() {
//地圖圖層
this.layer = new TileLayer({
source: new TileWMS({
//不能設置為0,否則地圖不展示。
ratio: 1,
url: "http://localhost:8000/geoserver/nyc/wms",
params: {
LAYERS: "nyc:nyc_roads",
STYLES: "",
VERSION: "1.1.1",
tiled: true,
},
serverType: "geoserver",
}),
});
//線的圖層
this.lineSource = new VectorSource({ wrapX: false });
this.lineLayer = new VectorLayer({
source: this.lineSource,
});
this.map = new Map({
//地圖容器ID
target: "map",
//引入地圖
layers: [this.layer, this.lineLayer],
view: new View({
//地圖中心點
center: [987777.93778, 213834.81024],
zoom: 14,
minZoom: 6, // 地圖縮放最小級別
maxZoom: 19,
}),
});
},
// 測量距離
formatLength(line) {
//計算平面距離
var length = getLength(line);
//定義輸出變量
var output;
//如果長度大於1000,則使用km單位,否則使用m單位
if (length > 1000) {
output = Math.round((length / 1000) * 100) / 100 + " " + "km";
} else {
output = Math.round(length * 100) / 100 + " " + "m";
}
return output;
},
},
};
</script>
<style scoped>
.map {
width: 100%;
height: 800px;
}
</style>
