openlayer实现webgis端绘制制图及编辑

在WebGIS端制图是指通过Web浏览器界面实现地理信息数据的可视化、编辑、分析以及地图产品的制作。这一过程通常涉及以下几个关键环节:

**1. 前端技术栈:

•HTML/CSS/JavaScript:作为Web开发的基础,用于构建用户界面布局、样式设计以及交互逻辑。

•Web地图库:

•Leaflet、OpenLayers、Mapbox GL JS等开源库,提供地图容器、图层管理、交互控件等功能,便于快速构建Web地图应用。

•GIS服务接口:

•Web Map Service (WMS):用于请求地图影像瓦片。

•Web Feature Service (WFS):用于获取矢量地理数据。

•Web Coverage Service (WCS):用于获取栅格数据。

•GeoJSON、TopoJSON、KML等数据格式,直接嵌入或通过API加载。

•地图样式与主题:

•Mapbox Studio、QGIS Cloud等在线工具,或使用JSON-based样式语言(如Mapbox Style Specification、OpenLayers Style Format)自定义地图样式。

**2. 数据准备与集成:

•数据源接入:

连接本地或远程GIS服务器、云存储(如AWS S3、Azure Blob Storage)、开放数据平台(如OpenStreetMap、ArcGIS Online)等,获取所需GIS数据。

•数据处理:

•对接地理编码服务(如Google Maps Geocoding API、Mapbox Geocoding API)进行地址解析或逆地理编码。

•使用客户端库(如Turf.js、Mapbox GL Geostats)进行空间分析、统计计算。

•缓存与优化:

•利用客户端缓存(如IndexedDB、localStorage)存储常用数据或结果,提高加载速度。

•使用矢量瓦片、切片金字塔技术优化大规模数据展示。

**3. 地图交互设计:

•基础交互:缩放、平移、旋转地图,开启/关闭图层,调整图层透明度等。

•高级交互:

•查询与标注:实现点击查询、范围选择、热点分析等功能,显示相关信息或动态标注。

•编辑与绘图:支持用户在地图上添加、修改、删除地理要素,如使用Leaflet.draw、OpenLayers Editing等插件。

•路由规划:集成路线规划服务(如OSRM、GraphHopper),提供驾车、步行、骑行路径规划。

•空间分析:在浏览器端进行简单分析操作,如缓冲区分析、叠加分析等。

**4. 地图定制与输出:

•地图样式定制:通过调整颜色、图标、文字样式等元素,创建符合项目主题的地图样式。

•地图打印与导出:

•实现Web页面打印预览,支持自定义打印范围、比例尺、布局等。

•提供地图截图、PDF导出功能,或集成地图打包服务(如Mapfish Print、GeoServer Print)。

•地图分享与嵌入:

•提供短链接、嵌入代码,方便用户将地图分享至社交媒体或嵌入到其他网站。

**5. 跨平台兼容与响应式设计:

•移动端适配:确保地图应用在不同尺寸的移动设备上具有良好用户体验,如使用触屏手势、自适应布局。

•多浏览器支持:测试在主流浏览器(Chrome、Firefox、Safari、Edge)上的兼容性。

**6. 性能监控与优化:

•性能指标跟踪:监控地图加载时间、内存占用、网络请求等指标,识别性能瓶颈。

•优化措施:

•压缩与合并静态资源,减少HTTP请求。

•使用Web Workers进行大数据处理,避免阻塞主线程。

•采用矢量瓦片、LOD(Level of Detail)策略,按需加载数据。通过上述技术手段和流程,WebGIS端制图实现了从数据获取、处理到地图展现、交互的全流程操作,让用户能够在Web浏览器环境中便捷地进行地图制作与分析,满足各种GIS应用场景的需求。

关键代码实现

组件化代码:

import Draw from 'ol/interaction/Draw'
import VectorSource from 'ol/source/Vector';
import VectorLayer from 'ol/layer/Vector';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';import {unByKey} from 'ol/Observable.js';
import Overlay from 'ol/Overlay';
import {getArea, getLength} from 'ol/sphere.js';
import View from 'ol/View';
import {LineString, Polygon} from 'ol/geom.js';
import {Circle as CircleStyle, Fill, Stroke, Style} from 'ol/style.js';
import {generateUUID, getLayerByCode} from "@/components/iClientOpenLayers/MapCommon";var DrawMap= /** @class */ (function () {function DrawMap(map, drawMapType,drawType,freeHand) {/*** Currently drawn feature.* @type {module:ol/Feature~Feature}*/this.sketch=null;this.freeHand=freeHand;/*** The help tooltip element.* @type {Element}*/this.helpTooltipElement=null;/*** Overlay to show the help messages.* @type {module:ol/Overlay}*/this.helpTooltip=null;/*** The drawMap tooltip element.* @type {Element}*/this.drawMapTooltipElement=null;/*** Overlay to show the drawMapment.* @type {module:ol/Overlay}*/this.drawMapTooltip=null;/*** Message to show when the user is drawing a polygon.* @type {string}*/this.continuePolygonMsg = '继续点击绘制多边形';/*** Message to show when the user is drawing a line.* @type {string}*/this.continueLineMsg = '继续点击绘制线';this.map=map;this.drawMapType=drawMapType;this.draw=null;this.listener=null;this.source=null;// var layer ;// 获取存放feature的vectorlayer层。map初始化的时候可以添加好了for(let layerTmp of map.getLayers().getArray()){if(layerTmp.get("name")=="DrawMap"){this.source= layerTmp.getSource();}}if(this.source==undefined||this.source==null){this.source=getLayerByCode(this.map,"CRegion").getSource()// this.source = new VectorSource();// var vector = new VectorLayer({//     source: this.source,//     style: new Style({//         fill: new Fill({//             color: 'rgba(255, 255, 255, 0.2)',//         }),//         stroke: new Stroke({//             color: '#ffcc33',//             width: 2,//         }),//         image: new CircleStyle({//             radius: 7,//             fill: new Fill({//                 color: '#ffcc33',//             }),//         }),//     }),// });// vector.set("name","DrawMap");// vector.set("code","DrawMap");// this.map.addLayer(vector);}if(drawType=="DrawMap"){this.createDrawMapTooltip();this.createHelpTooltip();let that=this;this.pointerMoveHandler = function (evt) {if (evt.dragging) {return;}/** @type {string} */var helpMsg = '请点击开始绘制';if (that.sketch) {var geom = (that.sketch.getGeometry());if (geom instanceof Polygon) {helpMsg = that.continuePolygonMsg;} else if (geom instanceof LineString) {helpMsg = that.continueLineMsg;}}that.helpTooltipElement.innerHTML = helpMsg;that.helpTooltip.setPosition(evt.coordinate);that.helpTooltipElement.classList.remove('hidden');};/*** Handle pointer move.* @param {module:ol/MapBrowserEvent~MapBrowserEvent} evt The event.*/map.on('pointermove', this.pointerMoveHandler);map.getViewport().addEventListener('mouseout',() =>{this.helpTooltipElement.classList.add('hidden');});// 量测调用this.addInteraction();}else if(drawType=="Draw"){// 量测调用this.addInteractionEx();}};DrawMap.prototype. formatLength = function (line) {var length = getLength(line,{projection:'EPSG:4326'});var output;if (length > 100) {output = (Math.round(length / 1000 * 100) / 100) +' ' + 'km';} else {output = (Math.round(length * 100) / 100) +' ' + 'm';}return output;};DrawMap.prototype. formatArea = function (polygon) {var area = getArea(polygon,{projection:'EPSG:4326'});var output;if (area > 10000) {output = (Math.round(area / 1000000 * 100) / 100) +' ' + 'km<sup>2</sup>';} else {output = (Math.round(area * 100) / 100) +' ' + 'm<sup>2</sup>';}return output;};DrawMap.prototype.addInteraction=function() {var type = (this.drawMapType == 'area' ? 'Polygon' : 'LineString');this.draw = new Draw({ol_uid:'draw',source: this.source,type: type,snapTolerance:20,freehand: this.freeHand,style: new Style({fill: new Fill({color: 'rgba(255, 255, 255, 0.2)'}),stroke: new Stroke({color: 'rgba(0, 0, 0, 0.5)',lineDash: [10, 10],width: 2}),image: new CircleStyle({radius: 5,stroke: new Stroke({color: 'rgba(0, 0, 0, 0.7)'}),fill: new Fill({color: 'rgba(255, 255, 255, 0.2)'})})})});this.map.addInteraction(this.draw);this.draw.on('drawstart',(evt)=> {// set sketchthis.sketch = evt.feature;/** @type {module:ol/coordinate~Coordinate|undefined} */var tooltipCoord = evt.coordinate;this.listener = this.sketch.getGeometry().on('change', (evt)=> {var geom = evt.target;var output;if (geom instanceof Polygon) {output = this.formatArea(geom);tooltipCoord = geom.getInteriorPoint().getCoordinates();} else if (geom instanceof LineString) {output = this.formatLength(geom);tooltipCoord = geom.getLastCoordinate();}this.drawMapTooltipElement.innerHTML = output;this.drawMapTooltip.setPosition(tooltipCoord);});}, this);this.draw.on('drawend',(e)=> {this.drawMapTooltipElement.className = 'ol-tooltip ol-tooltip-static';this.drawMapTooltip.setOffset([0, -7]);let cFeature = e.feature;cFeature.values_["ID"]=generateUUID()// unset sketchthis.clearDraw();}, this);};DrawMap.prototype.addInteractionEx=function(){var type = (this.drawMapType == 'area' ? 'Polygon' : 'LineString');if(this.drawMapType=="Point"){type=this.drawMapType;}this.draw = new Draw({source: this.source,type: type,freehand: this.freeHand,snapTolerance:20,});this.draw.on('drawend',(e)=> {const geometry = e.feature.getGeometry()const corrdinates = geometry.getCoordinates()let cFeature = e.feature;cFeature.values_["ID"]=generateUUID()// unset sketchthis.clearDraw();}, this);this.map.addInteraction(this.draw);};DrawMap.prototype.createDrawMapTooltip=function() {if (this.drawMapTooltipElement) {this.drawMapTooltipElement.parentNode.removeChild(this.drawMapTooltipElement);}this.drawMapTooltipElement = document.createElement('div');this.drawMapTooltipElement.className = 'ol-tooltip ol-tooltip-drawMap';this.drawMapTooltip = new Overlay({element: this.drawMapTooltipElement,offset: [0, -15],positioning: 'bottom-center'});this.drawMapTooltip.set("name","DrawMap");debuggerthis.drawMapTooltip.getElement().style.display = ''this.map.addOverlay(this.drawMapTooltip);};DrawMap.prototype.createHelpTooltip=function () {if (this.helpTooltipElement) {this.helpTooltipElement.parentNode.removeChild(this.helpTooltipElement);}this.helpTooltipElement = document.createElement('div');this.helpTooltipElement.className = 'ol-tooltip hidden';this.helpTooltip = new Overlay({element: this.helpTooltipElement,offset: [15, 0],positioning: 'center-left'});this.map.addOverlay(this.helpTooltip);};DrawMap.prototype.clearDraw=function () {debuggerthis.sketch = null;// unset tooltip so that a new one can be createdthis.drawMapTooltipElement = null;// this.createDrawMapTooltip();if(this.listener!=undefined&&this.listener!=null){unByKey(this.listener);}try{this.map.un('pointermove', this.pointerMoveHandler);}catch (e){}if(this.draw!=undefined&&this.draw!=null){for(let i = 0; i < this.map.interactions.array_.length; i++){if(this.draw.ol_uid == this.map.interactions.array_[i].ol_uid){this.map.removeInteraction(this.map.interactions.array_[i]);break}}}if(this.helpTooltipElement!=undefined&&this.helpTooltipElement!=null){this.helpTooltipElement.classList.add('hidden');}if(this.helpTooltip!=undefined&&this.helpTooltip!=null){this.map.removeOverlay(this.helpTooltip);}};return DrawMap;
}());export {DrawMap};

调用代码:

//绘制制图切换
drawMapSwitch(pIndex){if(this.curDraw!=null){this.curDraw.clearDraw();this.curDraw=null;}if(pIndex==0){this.curDraw=new DrawMap(this.sMap, "LineString","Draw",false);}else if(pIndex==1){this.curDraw=new DrawMap(this.sMap, "area","Draw",false);}else if(pIndex==2){this.curDraw=new DrawMap(this.sMap, "Point","Draw",false);}else if(pIndex==3){this.curDraw=new DrawMap(this.sMap, "LineString","Draw",true);}else if(pIndex==4){this.curDraw=new DrawMap(this.sMap, "area","Draw",true);}else if(pIndex==5){for(let layerTmp of this.sMap.getLayers().getArray()){if(layerTmp.get("code")=="CRegion"){layerTmp.getSource().clear();break;}}for(let i=0;i<this.sMap.getOverlays().getArray().length;i++){if(this.sMap.getOverlays().getArray()[i].get("code")=="CRegion"){this.sMap.removeOverlay(this.sMap.getOverlays().getArray()[i]);i--;}}}else if(pIndex==6){let geojson=getGeojsonByLayerCode(this.sMap,"CRegion")alert(geojson)}}

前端代码设计

<div class="operate map_huizhi"><i class="icon huizhi"></i><ul class="map-sub-nav"><li v-for="(item,index) in drawMapData" @click="drawMapSwitch(index)">{{item}}</li></ul>
</div>
.huizhi{width: 38px;height: 38px;background: url('./img/huizhi.png') no-repeat center center;background-image: -webkit-image-set(url('./img/huizhi.png') 1x, url("./img/huizhi@2x.png") 2x);background-image: image-set(url('./img/huizhi.png') 1x, url("./img/huizhi@2x.png") 2x);background-repeat: no-repeat;background-position: center center;
}

软件实现效果:

最后分享下地图下载器下载地址

通过百度网盘分享的文件:V-2.0jbr…
链接:https://pan.baidu.com/s/1AiFKTTknkEHkJ7t4nQ2P1g 
提取码:8664
复制这段内容打开「百度网盘APP 即可获取」

如果对您有所帮助,请点赞打赏支持!

技术合作交流qq:2401315930

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/807737.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Win11又来「重大」更新!

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 新建了免费的人工智能中文站https://ai.weoknow.com 新建了收费的人工智能中文站ai人工智能工具 更多资源欢迎关注 Windows 11预览通道的22635.3420版本迎来了几个比较大的改进&#xff0c;主要有三个方面&#xff1a; …

一种快速移植 OpenHarmony Linux 内核的方法

移植概述 本文面向希望将 OpenHarmony 移植到三方芯片平台硬件的开发者&#xff0c;介绍一种借助三方芯片平台自带 Linux 内核的现有能力&#xff0c;快速移植 OpenHarmony 到三方芯片平台的方法。 移植到三方芯片平台的整体思路 内核态层和用户态层 为了更好的解释整个内核…

python-study-day1-(病人管理系统-带sql)

MainWindow代码 from tkinter import * from tkinter import messagebox from tkinter.ttk import Comboboxclass MianWindow(Frame):def __init__(self, masterNone):super().__init__(master, padx30, pady20)self.flag 0self.pack(expandTrue, fillBOTH)self.id StringVa…

深入OceanBase内部机制:系统架构与组件精讲

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 目录 1️⃣OceanBase 整体架构1.1 分区1.2 分片1.3 日志流1.4 对等节点1.5 多租户 2️⃣OceanBase 架构与组件详解2.1 存储层2.2 …

Disk Drill Enterprise for Mac v5.5.1515数据恢复软件中文版

Disk Drill 是 Mac 操作系统固有的Mac数据恢复软件&#xff1a;使用 Recovery Vault 轻松保护文件免遭意外删除&#xff0c;并从 Mac 磁盘恢复丢失的数据。支持大多数存储设备&#xff0c;文件类型和文件系统。 软件下载&#xff1a;Disk Drill Enterprise for Mac v5.5.1515激…

keepalived2.2.8+drbd9+nfs高可用存储部署

目录 一.本文基于上一篇文章keepalived环境来做的&#xff0c;主机信息如下 二.为两台虚拟机准备添加一块新硬盘设备 三.安装drbd9 1.使用扩展源的rpm包来下载 2.创建资源并挂载到新增的硬盘 3.主设备升级身份 4.主备两个设备手动切换身份演示 四.安装配置nfs 五.安装…

【YOLOv8】Yolov5和Yolov8网络结构的分析与对比

目录 一 YOLOv5 二 YOLOv8 yolo通常采用backbone-neck-head的网络结构。 Backbone 主要负责从输入图像中提取高层次的语义特征,常包含多个卷积层和池化层&#xff0c;构建了一个深层次的特征提取器。Neck通常用来进一步整合与调整backbone提取的特征&#xff0c;有利于将不同…

大话设计模式——24.迭代器模式(Iterator Pattern)

简介 提供一种方法顺序访问一个聚合对象中各个元素&#xff0c;而又不暴露该对象的内部实现。&#xff08;Java中使用最多的设计模式之一&#xff09; UML图 应用场景 Java的集合对象&#xff1a;Collection、List、Map、Set等都有迭代器Java ArrayList的迭代器源码 示例 简…

uniapp的h5项目 用命令起这个项目(vue-cli)

这里其实就相当于给uniapp h5套了一个vue-cli的壳&#xff08;纯属个人感觉&#xff09; 首先需要安装vue-cli 脚手架 npm install -g vue/cli然后创建项目&#xff08;这里需要在hbuilder创建&#xff09; vue create -p dcloudio/uni-preset-vue uniapp安装成功后它的结构…

OSCP靶场--Dibble

OSCP靶场–Dibble 考点(前端鉴权参数修改node.js代码注入 suid cp提权 ) 1.nmap扫描 ## ┌──(root㉿kali)-[~/Desktop] └─# nmap 192.168.173.110 -sV -sC -Pn --min-rate 2500 -p- Starting Nmap 7.92 ( https://nmap.org ) at 2024-04-09 06:36 EDT Nmap scan repor…

Jackson配置处理LocalDateTime、LocalDate等java8时间类型失效的问题解决

目录 前言 一、问题排查过程 1.1 SpringMvc是如何处理请求报文和响应报文 1.2 JacksonConfig配置排查 二、导致Jackson配置失效的原因 2.1 没有addSerializer 2.2 添加了EnableMvc注解 2.3 另外有地方配置了Jacksonhttpconver覆盖了配置 总结 前言 上一篇文章《使用Ja…

C/C++的内存管理

栈帧最主要的作用就是存储局部数据 C语言中动态内存管理方式 C语言动态内存管理 该篇详细的讲述了C语言动态内存管理的使用&#xff0c;不太懂的小伙伴可以去了解一下 C中动态内存管理方式 首先&#xff0c;C语言内存管理的方式在C中可以继续使用。但有些地方就无能为力而且使用…

Volatility-内存取证案例1-writeup--xx大赛

题目提示&#xff1a;flag{中文} 按部就班 &#xff08;1&#xff09;获取内存镜像版本信息 volatility -f 文件名 imageinfo 通过上述可知&#xff0c;镜像版本为Win7SP1X64。 &#xff08;2&#xff09;获取进程信息&#xff1a; volatility -f 镜像名 --profile第一步获取…

关于AI Agent、RAG技术揭秘:如何让人工智能更懂你?

人工智能技术正以前所未有的速度改变着我们的世界。从深度学习算法的突破到自动化和机器学习技术的进步。在这个变革的时代&#xff0c;几种前沿技术尤其引人注目&#xff0c;其中包括RAG&#xff08;Retrieval-Augmented Generation&#xff09;、AI Agent以及多模态技术。 近…

工频磁场抗扰度概述及相关注意事项

工频磁场 是指交流输变电设施产生的磁场&#xff0c;工频又称电力频率。 工频的特点是频率低、波长长&#xff1b;我国工频是50赫(Hz)&#xff0c;波长是6000千米(Km&#xff09; 工频磁场的抗扰度试验&#xff08;在有电流流过的地方都会伴生磁场&#xff0c;为了检查设备或系…

pmp就是智商税?

首先要明白的是&#xff0c;证书的价值并不在于证书本身&#xff0c;而在于学习过程中所获得的知识和经验&#xff0c;这才是证书真正的价值&#xff0c;是无法被复制的个人能力。 学习和考证都是经验的积累&#xff0c;通过这个过程可以不断地获取所需的知识&#xff0c;并加…

【Cesium学习笔记】一、加载Cesium并更换天地图底图

【Cesium学习笔记】一、加载Cesium 一、加载Cesium二、用Viewer显示地球三、更换天地图底图 Ps:本教程所有代码于同一个工程中&#xff0c;运行npm run dev默认首页为App.vue&#xff0c;只需替换App.vue的内容即可切换不同页面。 一、加载Cesium 本项目使用nvm管理node版本&…

微服务学习2

目录 一.网关路由 1.1.认识网关 1.2网关快速入门 1.2.1.创建项目 1.2.2.引入依赖 1.2.3.启动类 1.2.4.配置路由 1.3.路由过滤 二.网关登录校验 2.1网关请求处理流程 2.2网关过滤器 2.2.2网关过滤器 2.3自定义GlobalFilter 2.4.登录校验 2.4.1.JWT工具 2.4.2.登…

论文发表|《课外语文》期刊点评_投稿指南

论文发表|《课外语文》期刊点评_投稿指南 《课外语文》 知网 3版3300字符 全包 24年11-12月 可加急9-10月&#xff0c;次月出刊 &#xff08;操作周期2-3个月&#xff0c;文章不是教学类&#xff0c;不要摘要参考文献&#xff09; 《课外语文》杂志创刊于2002年&#xff…

SpringCloud集成Skywalking链路追踪和日志收集

1. 下载Agents https://archive.apache.org/dist/skywalking/java-agent/9.0.0/apache-skywalking-java-agent-9.0.0.tgz 2. 上传到服务器解压 在Spring Cloud项目中&#xff0c;每部署一个服务时&#xff0c;就拷贝一份skywalking的agent文件到该服务器上并解压。不管是部署…