首页 > 其他分享 >Vue+Openlayers实现绘制线段并测量距离显示

Vue+Openlayers实现绘制线段并测量距离显示

时间:2023-03-22 10:06:01浏览次数:38  
标签:map Vue 线段 ol Openlayers measureTooltipElement import null self


场景


在上面已经实现交互式绘制线段基础上,怎样实现测量距离。

Vue+Openlayers实现绘制线段并测量距离显示_前端

注:

关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。

实现

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>

标签:map,Vue,线段,ol,Openlayers,measureTooltipElement,import,null,self
From: https://blog.51cto.com/BADAOLIUMANGQZ/6142070

相关文章

  • vue-element-template去除登录
    一、修改src目录下的permission.js文件1、注释//if(hasToken){//if(to.path==='/login'){////ifisloggedin,redirecttothehomepage//next({path:......
  • maui BlazorWebView+本地html (vue、uniapp等都可以) 接入支付宝sdk 进行支付宝支付
     首先添加支付宝sdk的绑定库  nuget包:Chi.MauiBinding.Android.AliPay项目地址:https://github.com/realZhangChi/MauiBinding新建mauiBlazor应用,在根目录创建一......
  • #yyds干货盘点#vue设置跨域proxy
    创建​​vue.config.js​​文件//方法1module.exports={devServer:{host:'localhost',port:'8083',proxy:{'/api':{//......
  • vue.js项目打包报错Error: You appear to be using a native ECMAScript module confi
    问题描述报错:Error:YouappeartobeusinganativeECMAScriptmoduleconfigurationfile,whichisonlysupportedwhenrunningBabelasynchronously.原因是我......
  • Vue2 快速上手
    1.声明式渲染通过{{}}将数据渲染到页面:<body><divid="app">{{message}}</div></body><script>varapp=newVue({el:'#app',......
  • Vue10*10图片表格的点击效果
    要求.使用Vue及自定义组件完成10*10图片表格点击效果效果图过程:一.用PS切图1.打开PS,选择切图工具,在左边复选框选择切图工具。  2.单击右键鼠标,选择划分切片。......
  • 使用vue完成图片表格的点击因隐藏效果
    首先了解整个项目可以分几个板块。图片的切割,图片放入的框架构建,图片放入。1.图片的分割,这里的图片分割可以使用PS,或者网上搜图片切割的网站上传图片就行(http://www.zuoha......
  • vue 默认margin:8px
    #问题情景之前新拉取的vue项目,今天在更换背景图片的时候,发现,图片与顶部有缝隙,查看后发现,body属性中有margin:8px的属性,但是我程序代码中,外层并没有相关设置,且该body是在我......
  • vue 添加 不蒜子 统计计数
    #之前都是在jq环境当中使用卜算子的,感觉还是比较方便#现在使用vue搭建个人博客,当然也要入乡随俗了#步入正题1.环境依赖安装yarnaddbusuanzi.pure.js#ornpminstallb......
  • 详解uniapp和vue在路由方面的不同和联系
    Uniapp和Vue在路由方面有相似之处,因为Uniapp是基于Vue的。Uniapp的路由系统是通过VueRouter实现的,因此两者有许多相同的概念和API。相同点:都支持基于URL......