台州网站排名公司,网站设计图能用ps做么,兰州网站制作公司服务电话,专业建站公司的业务内容摘要 在 WebGIS 开发中#xff0c;OpenLayers 是一个非常强大的开源地图库#xff0c;它可以在 Web 应用中渲染高效的地图。本篇文章将介绍如何在 Vue 3 中使用 OpenLayers#xff0c;并封装一个自定义地图控件组件#xff0c;实现地图的放大、缩小、长度测量和面积测量功能… 摘要 在 WebGIS 开发中OpenLayers 是一个非常强大的开源地图库它可以在 Web 应用中渲染高效的地图。本篇文章将介绍如何在 Vue 3 中使用 OpenLayers并封装一个自定义地图控件组件实现地图的放大、缩小、长度测量和面积测量功能。 1. 项目介绍
在 WebGIS 相关的前端开发中OpenLayers 是一个流行的选择。结合 Vue 3我们可以利用 Composition API 更好地封装和管理地图逻辑使代码更加清晰和可维护。
本篇文章将介绍如何在 Vue 3 项目中集成 OpenLayers并基于此封装一个自定义地图组件提供以下功能
放大Zoom In缩小Zoom Out测量长度Measure Length测量面积Measure Area 2. 安装 OpenLayers
首先我们需要在 Vue 3 项目中安装 OpenLayers。
1创建 Vue 3 项目
如果你还没有 Vue 3 项目可以使用以下命令创建一个新的 Vue 3 项目
npm create vitelatest vue3-openlayers --template vue
cd vue3-openlayers
npm install
2安装 OpenLayers
运行以下命令安装 OpenLayers
npm install ol 3. 编写 OpenLayers 自定义组件
在 components 目录下创建 OpenLayersMap.vue 组件该组件负责加载地图并提供交互功能。
完整代码
!--* Author: 彭麒* Date: 2025/2/14* Email: 1062470959qq.com* Description: 此源码版权归吉檀迦俐所有可供学习和借鉴或商用。--
templatediv classcontainerdiv classw-full flex justify-center flex-wrapdiv classfont-bold text-[24px]在Vue3中使用OpenLayers自定义组件放大、缩小、长度测量、面积测量/div/divdiv classcontrolboxdiv classgetlength0 clickgetLength(length)/divdiv classgetarea0 clickgetArea(area)/divdiv classzoomIn clickzoomIn/divdiv classzoomOut clickzoomOut/div/divdiv idvue-openlayers/div/div
/templatescript setup
import { onMounted, ref } from vue;
import ol/ol.css;
import { Map, View } from ol;
import Tile from ol/layer/Tile;
import OSM from ol/source/OSM;
import MeasureTool from /utils/OpenLayersMeasure.ts;
import * as control from ol/control;const map ref(null);const zoomIn () {if (map.value) {let czoom map.value.getView().getZoom();map.value.getView().setZoom(czoom 1);}
};const zoomOut () {if (map.value) {let czoom map.value.getView().getZoom();map.value.getView().setZoom(czoom - 1);}
};const getLength (type) {clearMeasure();MeasureTool.measure(map.value, type, true);
};const getArea (type) {clearMeasure();MeasureTool.measure(map.value, type, true);
};const clearMeasure () {MeasureTool.measure(map.value, , false);
};const initMap () {let raster new Tile({source: new OSM(),name: OSM,});map.value new Map({target: vue-openlayers,layers: [raster],view: new View({center: [-12000000, 4700000],zoom: 2,}),controls: control.defaults({zoom: false,rotate: false,attribution: false,}).extend([]),});
};onMounted(() {initMap();
});
/scriptstyle scoped
.container {width: 840px;height: 590px;margin: 50px auto;border: 1px solid #42B983;position: relative;
}#vue-openlayers {width: 800px;height: 470px;margin: 0 auto;border: 1px solid #42B983;position: relative;
}.controlbox {position: absolute;z-index: 200;bottom: 50px;width: 30px;padding: 5px 7px;height: 120px;right: 30px;border: 1px solid #ccc;border-radius: 4px;cursor: pointer;display: flex;align-content: space-between;flex-direction: column;background-color: #fff;
}.getlength0 {width: 18px;height: 30px;background: url(/assets/OpenLayers/getlength.png) center center no-repeat;background-size: 16px 16px;
}.getarea0 {width: 18px;height: 30px;background: url(/assets/OpenLayers/getarea.png) center center no-repeat;background-size: 16px 16px;
}.zoomIn {width: 18px;height: 30px;background: url(/assets/OpenLayers/zoomin.png) center center no-repeat;background-size: 16px 16px;
}.zoomOut {width: 18px;height: 30px;background: url(/assets/OpenLayers/zoomout.png) center center no-repeat;background-size: 16px 16px;
}
/style4. 测量工具 OpenLayersMeasure.ts
创建 utils/OpenLayersMeasure.ts 文件封装 OpenLayers 的测量功能
import Draw from ol/interaction/Draw;
import VectorSource from ol/source/Vector;
import VectorLayer from ol/layer/Vector;
import Point from ol/geom/Point;
import { unByKey } from ol/Observable;
import Overlay from ol/Overlay;
import { Feature } from ol;
import { getArea, getLength } from ol/sphere;
import LineString from ol/geom/LineString;
import Polygon from ol/geom/Polygon;
import { Circle as CircleStyle, Fill, Stroke, Style } from ol/style;export default {measure(map, measureType, show) {let source new VectorSource(); // 创建一个新的矢量源let sketch; // 当前绘制的要素let helpTooltipElement; // 帮助提示元素let helpTooltip; // 显示帮助消息的覆盖层let measureTooltipElement; // 测量提示元素let measureTooltip; // 显示测量结果的覆盖层const continuePolygonMsg ; // 绘制多边形时显示的消息const continueLineMsg ; // 绘制线条时显示的消息createMeasureTooltip(); // 创建测量提示createHelpTooltip(); // 创建帮助提示const pointerMoveHandler function (evt) {if (evt.dragging) {return;}let helpMsg 请点击开始绘制; // 默认帮助消息if (sketch) {const geom sketch.getGeometry();if (geom instanceof Polygon) {helpMsg continuePolygonMsg; // 如果是多边形显示相应消息} else if (geom instanceof LineString) {helpMsg continueLineMsg; // 如果是线条显示相应消息}}helpTooltipElement.innerHTML helpMsg; // 更新帮助提示内容helpTooltip.setPosition(evt.coordinate); // 设置帮助提示位置helpTooltipElement.classList.remove(hidden); // 显示帮助提示};map.on(pointermove, pointerMoveHandler); // 监听指针移动事件map.getViewport().addEventListener(mouseout, function () {helpTooltipElement.classList.add(hidden); // 鼠标移出视口时隐藏帮助提示});let draw; // 绘制交互const formatLength function (line) {const sourceProj map.getView().getProjection(); // 获取投影坐标系const length getLength(line, { projection: sourceProj }); // 计算长度let output;if (length 100) {output (Math.round(length / 1000 * 100) / 100) km; // 如果长度大于100米显示为公里} else {output (Math.round(length * 100) / 100) m; // 否则显示为米}return output;};const formatArea function (polygon) {const sourceProj map.getView().getProjection(); // 获取投影坐标系const area getArea(polygon, { projection: sourceProj }); // 计算面积let output;if (area 10000) {output (Math.round(area / 1000000 * 100) / 100) kmsup2/sup; // 如果面积大于10000平方米显示为平方公里} else {output (Math.round(area * 100) / 100) msup2/sup; // 否则显示为平方米}return output;};for (const layerTmp of map.getLayers().getArray()) {if (layerTmp.get(name) feature) {source layerTmp.getSource(); // 获取存放要素的矢量层}}function addInteraction() {const type (measureType area ? Polygon : LineString); // 根据测量类型设置绘制类型draw new Draw({source: source,type: type,style: new Style({fill: new Fill({color: rgba(255, 255, 255, 0.2), // 填充颜色}),stroke: new Stroke({color: rgba(255, 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), // 圆点填充颜色}),}),}),});map.addInteraction(draw); // 添加绘制交互let listener;draw.on(drawstart, function (evt) {sketch evt.feature; // 设置当前绘制的要素let tooltipCoord evt.coordinate; // 提示坐标listener sketch.getGeometry().on(change, function (evt) {const geom evt.target;let output;if (geom instanceof Polygon) {output formatArea(geom); // 格式化面积tooltipCoord geom.getInteriorPoint().getCoordinates(); // 获取多边形内部点坐标} else if (geom instanceof LineString) {output formatLength(geom); // 格式化长度tooltipCoord geom.getLastCoordinate(); // 获取线条最后一个点的坐}measureTooltipElement.innerHTML output; // 更新测量提示内容measureTooltip.setPosition(tooltipCoord); // 设置测量提示位置});map.on(dblclick, function (evt) {const point new Point(evt.coordinate);source.addFeature(new Feature(point)); // 添加双击点要素});});draw.on(drawend, function () {measureTooltipElement.className tooltip tooltip-static; // 设置测量提示样式measureTooltip.setOffset([0, -7]); // 设置测量提示偏移sketch null; // 清空当前绘制的要素measureTooltipElement null; // 清空测量提示元素createMeasureTooltip(); // 创建新的测量提示unByKey(listener); // 移除监听器map.un(pointermove, pointerMoveHandler); // 移除指针移动事件监听map.removeInteraction(draw); // 移除绘制交互helpTooltipElement.classList.add(hidden); // 隐藏帮助提示});}function createHelpTooltip() {if (helpTooltipElement) {helpTooltipElement.parentNode.removeChild(helpTooltipElement); // 移除旧的帮助提示元素}helpTooltipElement document.createElement(div);helpTooltipElement.className tooltip hidden; // 设置帮助提示样式helpTooltip new Overlay({element: helpTooltipElement,offset: [15, 0], // 设置偏移positioning: center-left, // 设置定位方式});map.addOverlay(helpTooltip); // 添加帮助提示覆盖层}function createMeasureTooltip() {if (measureTooltipElement) {measureTooltipElement.parentNode.removeChild(measureTooltipElement); // 移除旧的测量提示元素}measureTooltipElement document.createElement(div);measureTooltipElement.className tooltip tooltip-measure; // 设置测量提示样式measureTooltip new Overlay({element: measureTooltipElement,offset: [0, -15], // 设置偏移positioning: bottom-center, // 设置定位方式});map.addOverlay(measureTooltip); // 添加测量提示覆盖层}addInteraction(); // 添加绘制交互const vector new VectorLayer({name: lineAndArea,source: source,style: new Style({fill: new Fill({color: rgba(255, 255, 255, 0.2), // 填充颜色}),stroke: new Stroke({color: red, // 线条颜色width: 2, // 线条宽度}),image: new CircleStyle({radius: 7, // 圆点半径fill: new Fill({color: #ffcc33, // 圆点填充颜色}),}),}),zIndex: 16, // 设置图层顺序});if (show measureType) {map.addLayer(vector); // 显示测量图层} else {map.getOverlays().clear(); // 清除所有覆盖层map.getLayers().getArray().forEach((layer, index, array) {if (layer.get(name) lineAndArea) {map.removeLayer(layer); // 移除测量图层}});}},
}; 5. 在 Vue 项目中使用组件
在 App.vue 中引入 OpenLayersMap.vue 组件
template div OpenLayersMap / /div
/template
script setup
import OpenLayersMap from /components/OpenLayersMap.vue;
/script 6. 运行项目
在项目根目录运行以下命令启动 Vue 开发服务器
npm run dev
然后在浏览器中访问 http://localhost:5173/你就可以看到 OpenLayers 地图并且可以使用放大、缩小、长度测量和面积测量功能了。 7. 结语
本篇文章介绍了如何在 Vue 3 项目中集成 OpenLayers并封装了一个自定义地图控件组件实现了放大、缩小、长度测量和面积测量功能。
你可以根据自己的需求扩展更多功能比如
添加更多测量单位显示测量结果的弹窗增加图层切换等功能
希望这篇文章能帮助到你如果你觉得有用请点赞支持 交流与讨论
如果你有任何问题或建议欢迎在评论区留言交流